延迟执行
从Linq查询过程看不断有新类型、集合构建、释放感觉效率不高但Linq延迟执行机制将大大改善常规操作加载整个数据源导致效率低下状况
举例:
void Main
{
collection = { 10, 11, 12, 13, 14 };
Console.WriteLine("Begin query collection:" + DateTime.Now);
var result = from i in collection
select DoubleInt(i);
Console.WriteLine("End query collection & Begin output:" + DateTime.Now);
foreach (var i in result)
{
Console.WriteLine("Result:" + i + " Time:" + DateTime.Now.);
}
Console.WriteLine("End output:" + DateTime.Now);
}
DoubleInt( i)
{
Console.WriteLine("The parameter is:" + i);
Thread.Sleep(1000);
i * 2;
}
// 输出为:
// Begin query collection:2008-9-12 22:41:50
// End query collection & Begin output:2008-9-12 22:41:50
// The parameter is:10
// Result:20 Time:2008-9-12 22:41:51
// The parameter is:11
// Result:22 Time:2008-9-12 22:41:52
// The parameter is:12
// Result:24 Time:2008-9-12 22:41:53
// The parameter is:13
// Result:26 Time:2008-9-12 22:41:54
// The parameter is:14
// Result:28 Time:2008-9-12 22:41:55
// End output:2008-9-12 22:41:55
从输出结果可以看出查询时并没有立即计算结果而是输出时才进行计算
其实在构造查询语句时只是传递相应操作委托并没有真正执行查询操作真正执行是在 IEnumerator<T> GetEnumerator 思路方法中执行每取得个元素就执行次延迟执行还有个好处是改变数据源时不需要构造新查询语句即可执行获得想要结果
举例:
void Main
{
// 原始集合
collection = { 10, 11, 12, 13, 14 };
// 查询集合
var result = from i in collection
select DoubleInt(i);
// 输出原集合
foreach (var i in result)
{
Console.WriteLine(i);
}
Console.WriteLine("Change data source:");
// 改变集合
for (var i = 0; i < collection.Length; i)
{
collection[i] 10;
}
// 输出改变后集合
foreach (var i in result)
{
Console.WriteLine(i);
}
}
DoubleInt( i)
{
i * 2;
}
// 结果:
// 20
// 22
// 24
// 26
// 28
// Change data source:
// 40
// 42
// 44
// 46
// 48
为了更清楚演示延迟执行执行时间自己实现 IEnumerator<T> 接口通过下面代码可以看出查询操作是在 GetEnumerator 思路方法中执行
void Main
{
collection = { 10, 11, 12, 13, 14 };
var result = from i in GetEnumerator(collection)
select i;
foreach (var i in result)
{
Console.WriteLine(i);
}
}
public IEnumerable<> GetEnumerator( collection)
{
foreach (var i in collection)
{
Console.WriteLine("Compute:" + i);
yield DoubleInt(i);
}
}
DoubleInt( i)
{
Console.WriteLine("The parameter is:" + i);
i * 2;
}
// 输出:
// Compute:10
// The parameter is:10
// 20
// Compute:11
// The parameter is:11
// 22
// Compute:12
// The parameter is:12
// 24
// Compute:13
// The parameter is:13
// 26
// Compute:14
// The parameter is:14
// 28
延迟执行优点是不需要同时加载整个数据源执行占用资源少、效率高试想如果数据源非常大全部加载效率会多低
当然某些时候延迟执行也会导致数据不致等等想要关闭延迟执行可以用ToList<T>、ToArray<T>等思路方法立即执行查询操作
前面介绍集合操作时会影响延迟操作因此在执行集合操作时应特别注意
下面例子演示立即执行
void Main
{
collection = { 10, 11, 12, 13, 14 };
Console.WriteLine("Begin query collection:" + DateTime.Now);
var result = from i in collection
select DoubleInt(i);
Console.WriteLine("End query collection & Begin output:" + DateTime.Now);
foreach (var i in result.ToList)
{
Console.WriteLine("Result:" + i + " Time:" + DateTime.Now.);
}
Console.WriteLine("End output & Begin get collection count:" + DateTime.Now);
// 集合操作:取元素数量
Console.WriteLine("元素数量为:" + result.Count);
Console.WriteLine("End get collection count:" + DateTime.Now);
}
DoubleInt( i)
{
Console.WriteLine("The parameter is:" + i);
Thread.Sleep(1000);
i * 2;
}
// 输出结果:
// Begin query collection:2008-9-12 23:36:34
// End query collection & Begin output:2008-9-12 23:36:34
// The parameter is:10
// The parameter is:11
// The parameter is:12
// The parameter is:13
// The parameter is:14
// Result:20 Time:2008-9-12 23:36:39
// Result:22 Time:2008-9-12 23:36:39
// Result:24 Time:2008-9-12 23:36:39
// Result:26 Time:2008-9-12 23:36:39
// Result:28 Time:2008-9-12 23:36:39
// End output & Begin get collection count:2008-9-12 23:36:39
// The parameter is:10
// The parameter is:11
// The parameter is:12
// The parameter is:13
// The parameter is:14
// 元素数量为:5
// End get collection count:2008-9-12 23:36:44
查询非泛型集合
在 .NET1.X 时代不支持泛型构造集合时都要转换或装箱为Object类型Linq 查询是以泛型为基础在老系统升级或整合时要进行非泛型集合操作EnumerableCast<T> 和OfType<T>扩展思路方法使非泛型集合 Linq 查询成为可能
ArrayList list = ArrayList;
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
var result = from i in list.Cast<>
select i;
foreach (var i in result)
{
Console.WriteLine(i);
}
// result:
// 1
// 2
// 3
// 4
// 5
如果不想显式Cast<T>思路方法可以在元素前面指定类型上面例子变为:
ArrayList list = ArrayList;
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
var result = from i in list
select i;
foreach (var i in result)
{
Console.WriteLine(i);
}
我们知道非泛型不是类型安全可以在非泛型ArrayList中同时插入整型、串那么上面思路方法进行类型转换会抛出异常影响操作继续进行OfType<T>可以定程度上避免这个问题如下面举例会选择适当类型而忽略不匹配类型
ArrayList list = ArrayList;
list.Add(1);
list.Add(2);
list.Add("abc");
list.Add(3);
list.Add(4);
var result = from i in list.OfType<>
select i;
foreach (var i in result)
{
Console.WriteLine(i);
}
// result:
// 1
// 2
// 3
// 4
如果这个例子中集合用上面Cast<T>或隐式转换将会抛出异常
最新评论