在 MSDN 中对 System.Linq.Enumerable 类的 AsEnumerable 方法相关描述如下所示:
实际上,这个方法只有一条语句,就是原样返回它的唯一参数:
使用 .NET Reflector 查看 .NET Framework 4.5 Class Library,就很清楚了:
这种只是原样返回它的唯一参数的方法有什么用呢?让我们来看一个例子吧:
1 using System; 2 using System.Linq; 3 using System.Collections.Generic; 4 5 namespace Skyiv.Test 6 { 7 static class LinqTester 8 { 9 class Firster<T> : List<T> { public T First() { return default(T); } } 10 static void Test<T>(Firster<T> x) { Console.WriteLine("F:" + x.First()); } 11 static void Test<T>(List<T> x) { Console.WriteLine("L:" + x.First()); } 12 static void Test<T>(IEnumerable<T> x) { Console.WriteLine("I:" + x.First()); } 13 14 static void Main() 15 { 16 var a = new Firster<int> { 2, 3, 5 }; 17 Test(a); 18 Test(a as List<int>); 19 Test(a.AsEnumerable()); 20 } 21 } 22 }
在上述程序中:
在 Arch Linux 的 Mono 环境下编译和运行:
work$ dmcs LinqTester.cs && mono LinqTester.exe F:0 L:2 I:2
上述运行结果解释如下:
如果在上述程序中,分别进行以下操作:
再重新编译和运行,分别会有什么结果呢?
前面的测试程序引用了 System.Linq 和 System.Collections.Generic 命名空间,涉及到的东东比较复杂。下面我们来一个简单点的测试程序:
1 using System; 2 3 namespace Skyiv.Test 4 { 5 class Thing { public string GetId() { return "Thing"; } } 6 7 static class Extensions 8 { 9 public static object AsObject(this object x) { return x; } 10 public static string GetId(this object x) { return "Object"; } 11 } 12 13 static class Tester 14 { 15 static void Main() 16 { 17 var a = new Thing(); 18 var b = a.AsObject(); 19 Console.WriteLine(a.GetId()); 20 Console.WriteLine(b.GetId()); 21 } 22 } 23 }
在上述程序中:
对于上述程序来说,第 18 行的语句使用下面任何一个都是等效的:
在 Arch Linux 操作系统的 Mono 环境中编译和运行:
work$ dmcs Tester.cs && mono Tester.exe Thing Object
上述运行结果解释如下:
使用 monodis 反汇编 Tester.exe,得到 Main 方法的 MSIL 代码如下所示:
1 .namespace Skyiv.Test 2 { 3 .class private auto ansi abstract sealed beforefieldinit Tester extends [mscorlib]System.Object 4 { 5 // method line 5 6 .method private static hidebysig default void Main () cil managed 7 { 8 // Method begins at RVA 0x2108 9 .entrypoint 10 // Code size 36 (0x24) 11 .maxstack 7 12 .locals init ( 13 class Skyiv.Test.Thing V_0, object V_1) 14 IL_0000: newobj instance void class Skyiv.Test.Thing::'.ctor'() 15 IL_0005: stloc.0 16 IL_0006: ldloc.0 17 IL_0007: call object class Skyiv.Test.Extensions::AsObject(object) 18 IL_000c: stloc.1 19 IL_000d: ldloc.0 20 IL_000e: callvirt instance string class Skyiv.Test.Thing::GetId() 21 IL_0013: call void class [mscorlib]System.Console::WriteLine(string) 22 IL_0018: ldloc.1 23 IL_0019: call string class Skyiv.Test.Extensions::GetId(object) 24 IL_001e: call void class [mscorlib]System.Console::WriteLine(string) 25 IL_0023: ret 26 } // end of method Tester::Main 27 } // end of class Skyiv.Test.Tester 28 }
上述 MSIL 代码中: