转换操作符是用来实现将输入对象的类型转变为序列的功能。名称以“As”开头的转换方法可更改源集合的静态类型但不枚举(延迟加载)此源集合。名称以“To”开头的方法可枚举(即时加载)源集合并将项放入相应的集合类型。
所有实现了IEnumerable
class AsEnumerableTest : List
{
public void Where(Func func)
{
Console.WriteLine("AsEnumerableTest的Where方法");
}
}
public static void AsEnumerable()
{
AsEnumerableTest q = new AsEnumerableTest() { 1,2,3,4 };
q.Where(r => r < 3);
//q.AsEnumerable().Where(r => r < 3);
//IEnumerable i = q;
//i.Where(r => r < 3);
}
Cast
如果集合中的元素无法强制转换为 T 类型,则此方法将引发异常。以下代码演示了这一过程:
ArrayList array = new ArrayList();
array.Add("Bob");
array.Add("Jack");
array.Add(1);
foreach (var item in array.Cast())
{
Console.WriteLine(item);
}
运行此代码,可以输出“Bob”、“Jack”,然后会报出一个异常“无法将int强制转换为string”,这说明Cast方法也是延迟执行实现的,只有在枚举过程中才将对象逐个强制转换为T类型。
OfType
ToArray 操作符可以在IEnumerable
ToDictionary操作符根据指定的键选择器函数,从IEnumerable
using (NorthwindDataContext db = new NorthwindDataContext())
{
db.Log = Console.Out; //将生成的T-SQL语句输出到控制台中
//方法语法
var q =
db.Categories
.ToDictionary
(
c => c.CategoryID,
c => c.CategoryName
);
foreach (var item in q)
{
Console.WriteLine("{0} - {1}",item.Key,item.Value);
}
}
需要注意的是,如果省略ToDictionary方法的第二个参数(值选择函数),那么Value将会保存一个类别对象。还有,如果Key为null,或者出现重复的Key,都将导致抛出异常。
ToList操作符可以在IEnumerable
ToLookup操作符将创建一个 Lookup
using (NorthwindDataContext db = new NorthwindDataContext())
{
db.Log = Console.Out; //将生成的T-SQL语句输出到控制台中
//方法语法
var q =
db.Products
.ToLookup
(
p => p.CategoryID,
p => p.ProductName
);
foreach (var item in q)
{
Console.WriteLine(item.Key);
foreach (var p in item)
{
Console.WriteLine(p);
}
}
}
可以看出,ToLookup操作与GroupBy操作很相似,只不过GroupBy是延迟加载的,而ToLookup是即使加载。
元素操作符将从一个序列中返回单个指定的元素。
First操作将返回序列中的第一个元素。如果序列中不包含任何元素,则First
using (NorthwindDataContext db = new NorthwindDataContext())
{
db.Log = Console.Out; //将生成的T-SQL语句输出到控制台中
//无参
var query =
db.Employees
.First();
//有参
var q =
db.Employees
.First(e => e.FirstName.StartsWith("S"));
Console.WriteLine(q.FirstName);
}
上述代码中使用了First
FirstOrDefault方法将返回序列中的第一个元素;如果序列中不包含任何元素,则返回默认值。它也可以像First方法一样传递一个条件。需要说明的是如果序列中不包含任何元素,返回的默认值是个怎样的元素。在这之前,先来看一下FirstOrDefault方法是如何实现的:
public static TSource FirstOrDefault(this IEnumerable source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
IList list = source as IList;
if (list != null)
{
if (list.Count > 0)
{
return list[0];
}
}
else
{
using (IEnumerator enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current;
}
}
}
return default(TSource);
}
1. 如果调用FirstOrDefault方法的序列为空,抛出异常
2. 如果序列成功转换为List
3. 如果序列没有成功转换为List
4. 如果上述操作都没有执行,则使用default(T)关键字返回类型T的默认值
以下给出MSDN中,对于default(T)关键字的描述:
在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T:
给定参数化类型 T 的一个变量 t,只有当 T 为引用类型时,语句 t = null 才有效;只有当 T 为数值类型而不是结构时,语句 t = 0 才能正常使用。解决方案是使用default 关键字,此关键字对于引用类型会返回 null,对于数值类型会返回零。对于结构,此关键字将返回初始化为零或 null 的每个结构成员,具体取决于这些结构是值类型还是引用类型。
Last方法将返回序列中的最后一个元素。使用方法参照First。
LastOrDefault方法将返回序列中的最后一个元素;如果序列中不包含任何元素,则返回默认值。使用方法参照FirstOrDefault。
ElementAt方法返回序列中指定索引处的元素。使用方法参照First。需要注意的是如果索引超出范围会导致异常。
ElementAtOrDefault方法将返回序列中指定索引处的元素;如果索引超出范围,则返回默认值。使用方法参照FirstOrDefault。
Single方法的无参形式将从一个序列中返回单个元素,如果该序列包含多个元素,或者没有元素数为0,则会引发异常。也就是说,在序列执行Single方法的无参形式时,必须保证该序列有且仅有一个元素。
Single方法的有参形式将从一个序列中返回符合指定条件的唯一元素,如果有多个元素,或者没有元素符合这一条件,则会引发异常。以下代码演示了Single的使用方式:
using (NorthwindDataContext db = new NorthwindDataContext())
{
db.Log = Console.Out; //将生成的T-SQL语句输出到控制台中
//方法语法
var q =
db.Employees
.Single();
var query =
db.Employees
.Single(e => e.FirstName.StartsWith("S"));
Console.WriteLine(query.FirstName);
}
SingleOrDefault方法的无参形式将从一个序列中返回单个元素。如果元素数为0,则返回默认值。如果该序列包含多个元素,则会引发异常。
SingleOrDefault方法的有参形式将从一个序列中返回符合指定条件的唯一元素,如果元素数为0,则返回默认值;如果该序列包含多个元素,则会引发异常。SingleOrDefault的使用方式与Single相同。
需要注意的是,Single方法与SingleOrDefault方法都是即时加载的,在代码进行到方法所在位置时,如果引发了异常,会立刻抛出。