通过IL 来解读yeid原理 与 延迟加载的实现

什么是延迟加载:延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。

那么如何实现延迟加载:让我们来思考一下,如何在真正的执行获取数据的时候才加载数据。
从前端的js 延迟加载图片来看,原理是
1、先确定布局
2、设置占位符(大白话:就是说 先设置好html的标签 例如 img标签 div标签) 。
3、绑定事件 (也就是条件判断 什么时候才真正记载)
4、激活事件时 通过js动态加载的方式 为这些标签加载要的内容

例如:<img src="#" data-src=“图片地址”/
因为src是# 所有没有立即加载图片资源 但是data-src里面保存的图片地址
然后通过绑定事件 来动态替换src
比较 image 的 offsetTop 与 seeHeight + scrollTop 的大小,当小于时则说明图片已经出现过在视口中,这时候继续判断图片是否已经替换过,如果没有替换过,则进行替换。
在这里插入图片描述
同理 在C# 中延迟加载 linq 或者 自定义的延迟加载原理也应该大致相同
1、确定代码运行逻辑
2、设置公式(方法 函数 )
3、设置条件 或者真正调用的方式
4、调用

来我们写一个伪代码

//简单来说就是把方法 当做了参数传递
//在真正调用的时候才执行这个方法参数 并输出结果
void main(){
	var witeMetho = funcA(公式x);
    ...
    .一堆逻辑判断后
    ...
	witeMetho.invoke(); //这个地方才被真的执行
}
void 公式x(){
	console.write("我被真正执行了")
}

接下来我们看看yeid 的运行原理
下面的样例代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YeidTest
{
    class Program
    {
        public static IEnumerable<int> InvokeYeid()
        {
            yield return 1;
            yield return 2;
            yield return 3;
        }

        static void Main(string[] args)
        {
            Console.WriteLine("直接输出");
            Console.WriteLine(InvokeYeid());

            Console.WriteLine("循环输出");
            foreach (var item in InvokeYeid())
            {
                Console.Write(item + "  ");
            }

            Console.WriteLine("");
            Console.WriteLine("ToList后输出");


            foreach (var item in InvokeYeid().ToList())
            {
                Console.Write(item + "  ");
            }

            Console.WriteLine("");
            Console.WriteLine("直接通过迭代输出");

            var enumerator = InvokeYeid().GetEnumerator();
            while (enumerator.MoveNext())
            {

                Console.Write(enumerator.Current + "  ");
            }

            Console.ReadLine();
        }
    }
}


结果在这里插入图片描述

奇怪的是 直接输出为什么不是 我们想象中的 1 或 2 或3呢 而是一个公式(方法 函数)
其实是因为yeid 实现了延迟加载 只有在迭代的时候 才会真真执行
这也是linq为什么只有 ToList()才会真正执行的原因
如何查看IL (如图)
在这里插入图片描述
Program方法的IL代码如下

 .class private auto ansi beforefieldinit YeidTest.Program
	extends [mscorlib]System.Object
{
	// 嵌套类型
	.class nested private auto ansi sealed beforefieldinit '<InvokeYeid>d__0'
		extends [mscorlib]System.Object
		implements class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>,
		           [mscorlib]System.Collections.IEnumerable,
		           class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>,
		           [mscorlib]System.Collections.IEnumerator,
		           [mscorlib]System.IDisposable
	{
		.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
			01 00 00 00
		)
		// 成员
		.field private int32 '<>2__current'
		.field private int32 '<>1__state'
		.field private int32 '<>l__initialThreadId'

		// 方法
		.method private final hidebysig newslot virtual 
			instance class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> 'System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator' () cil managed 
		{
			.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
				01 00 00 00
			)
			.override method instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
			// 方法起始 RVA 地址 0x2050
			// 方法起始地址(相对于文件绝对值:0x0250)
			// 代码长度 58 (0x3a)
			.maxstack 2
			.locals init (
				[0] class YeidTest.Program/'<InvokeYeid>d__0',
				[1] class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>,
				[2] bool
			)

			// 0x025C: 28 19 00 00 0A
			IL_0000: call int32 [mscorlib]System.Environment::get_CurrentManagedThreadId()
			// 0x0261: 02
			IL_0005: ldarg.0
			// 0x0262: 7B 03 00 00 04
			IL_0006: ldfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>l__initialThreadId'
			// 0x0267: 33 0F
			IL_000b: bne.un.s IL_001c

			// 0x0269: 02
			IL_000d: ldarg.0
			// 0x026A: 7B 02 00 00 04
			IL_000e: ldfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 0x026F: 1F FE
			IL_0013: ldc.i4.s -2
			// 0x0271: FE 01
			IL_0015: ceq
			// 0x0273: 16
			IL_0017: ldc.i4.0
			// 0x0274: FE 01
			IL_0018: ceq
			// 0x0276: 2B 01
			IL_001a: br.s IL_001d

			// 0x0278: 17
			IL_001c: ldc.i4.1

			// 0x0279: 00
			IL_001d: nop
			// 0x027A: 0C
			IL_001e: stloc.2
			// 0x027B: 08
			IL_001f: ldloc.2
			// 0x027C: 2D 0B
			IL_0020: brtrue.s IL_002d

			// 0x027E: 02
			IL_0022: ldarg.0
			// 0x027F: 16
			IL_0023: ldc.i4.0
			// 0x0280: 7D 02 00 00 04
			IL_0024: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 0x0285: 02
			IL_0029: ldarg.0
			// 0x0286: 0A
			IL_002a: stloc.0
			// 0x0287: 2B 07
			IL_002b: br.s IL_0034

			// 0x0289: 16
			IL_002d: ldc.i4.0
			// 0x028A: 73 0B 00 00 06
			IL_002e: newobj instance void YeidTest.Program/'<InvokeYeid>d__0'::.ctor(int32)
			// 0x028F: 0A
			IL_0033: stloc.0

			// 0x0290: 06
			IL_0034: ldloc.0
			// 0x0291: 0B
			IL_0035: stloc.1
			// 0x0292: 2B 00
			IL_0036: br.s IL_0038

			// 0x0294: 07
			IL_0038: ldloc.1
			// 0x0295: 2A
			IL_0039: ret
		} // 方法 '<InvokeYeid>d__0'::'System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator' 结束

		.method private final hidebysig newslot virtual 
			instance class [mscorlib]System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () cil managed 
		{
			.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
				01 00 00 00
			)
			.override method instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Collections.IEnumerable::GetEnumerator()
			// 方法起始 RVA 地址 0x2098
			// 方法起始地址(相对于文件绝对值:0x0298)
			// 代码长度 11 (0xb)
			.maxstack 1
			.locals init (
				[0] class [mscorlib]System.Collections.IEnumerator
			)

			// 0x02A4: 02
			IL_0000: ldarg.0
			// 0x02A5: 28 04 00 00 06
			IL_0001: call instance class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> YeidTest.Program/'<InvokeYeid>d__0'::'System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator'()
			// 0x02AA: 0A
			IL_0006: stloc.0
			// 0x02AB: 2B 00
			IL_0007: br.s IL_0009

			// 0x02AD: 06
			IL_0009: ldloc.0
			// 0x02AE: 2A
			IL_000a: ret
		} // 方法 '<InvokeYeid>d__0'::System.Collections.IEnumerable.GetEnumerator 结束

		.method private final hidebysig newslot virtual 
			instance bool MoveNext () cil managed 
		{
			.override method instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
			// 方法起始 RVA 地址 0x20b0
			// 方法起始地址(相对于文件绝对值:0x02b0)
			// 代码长度 131 (0x83)
			.maxstack 2
			.locals init (
				[0] bool CS$1$0000,
				[1] int32 CS$4$0001
			)

			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x02BC: 02
			IL_0000: ldarg.0
			// 0x02BD: 7B 02 00 00 04
			IL_0001: ldfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 0x02C2: 0B
			IL_0006: stloc.1
			// 0x02C3: 07
			IL_0007: ldloc.1
			// 0x02C4: 45 04 00 00 00 08 00 00 00 02 00 00 00 04 00 00 00 06 00 00 00
			IL_0008: switch (IL_0025, IL_001f, IL_0021, IL_0023)

			// 0x02D9: 2B 08
			IL_001d: br.s IL_0027

			// 0x02DB: 2B 22
			IL_001f: br.s IL_0043

			// 0x02DD: 2B 39
			IL_0021: br.s IL_005c

			// 0x02DF: 2B 50
			IL_0023: br.s IL_0075

			// 0x02E1: 2B 02
			IL_0025: br.s IL_0029

			// 0x02E3: 2B 54
			IL_0027: br.s IL_007d

			// 0x02E5: 02
			IL_0029: ldarg.0
			// 0x02E6: 15
			IL_002a: ldc.i4.m1
			// 0x02E7: 7D 02 00 00 04
			IL_002b: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 12,列 9
			// 0x02EC: 00
			IL_0030: nop
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 13,列 13
			// 0x02ED: 02
			IL_0031: ldarg.0
			// 0x02EE: 17
			IL_0032: ldc.i4.1
			// 0x02EF: 7D 01 00 00 04
			IL_0033: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>2__current'
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x02F4: 02
			IL_0038: ldarg.0
			// 0x02F5: 17
			IL_0039: ldc.i4.1
			// 0x02F6: 7D 02 00 00 04
			IL_003a: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 0x02FB: 17
			IL_003f: ldc.i4.1
			// 0x02FC: 0A
			IL_0040: stloc.0
			// 0x02FD: 2B 3E
			IL_0041: br.s IL_0081

			// 0x02FF: 02
			IL_0043: ldarg.0
			// 0x0300: 15
			IL_0044: ldc.i4.m1
			// 0x0301: 7D 02 00 00 04
			IL_0045: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 14,列 13
			// 0x0306: 02
			IL_004a: ldarg.0
			// 0x0307: 18
			IL_004b: ldc.i4.2
			// 0x0308: 7D 01 00 00 04
			IL_004c: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>2__current'
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x030D: 02
			IL_0051: ldarg.0
			// 0x030E: 18
			IL_0052: ldc.i4.2
			// 0x030F: 7D 02 00 00 04
			IL_0053: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 0x0314: 17
			IL_0058: ldc.i4.1
			// 0x0315: 0A
			IL_0059: stloc.0
			// 0x0316: 2B 25
			IL_005a: br.s IL_0081

			// 0x0318: 02
			IL_005c: ldarg.0
			// 0x0319: 15
			IL_005d: ldc.i4.m1
			// 0x031A: 7D 02 00 00 04
			IL_005e: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 15,列 13
			// 0x031F: 02
			IL_0063: ldarg.0
			// 0x0320: 19
			IL_0064: ldc.i4.3
			// 0x0321: 7D 01 00 00 04
			IL_0065: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>2__current'
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x0326: 02
			IL_006a: ldarg.0
			// 0x0327: 19
			IL_006b: ldc.i4.3
			// 0x0328: 7D 02 00 00 04
			IL_006c: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 0x032D: 17
			IL_0071: ldc.i4.1
			// 0x032E: 0A
			IL_0072: stloc.0
			// 0x032F: 2B 0C
			IL_0073: br.s IL_0081

			// 0x0331: 02
			IL_0075: ldarg.0
			// 0x0332: 15
			IL_0076: ldc.i4.m1
			// 0x0333: 7D 02 00 00 04
			IL_0077: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16,列 9
			// 0x0338: 00
			IL_007c: nop

			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x0339: 16
			IL_007d: ldc.i4.0
			// 0x033A: 0A
			IL_007e: stloc.0
			// 0x033B: 2B 00
			IL_007f: br.s IL_0081

			// 0x033D: 06
			IL_0081: ldloc.0
			// 0x033E: 2A
			IL_0082: ret
		} // 方法 '<InvokeYeid>d__0'::MoveNext 结束

		.method private final hidebysig specialname newslot virtual 
			instance int32 'System.Collections.Generic.IEnumerator<System.Int32>.get_Current' () cil managed 
		{
			.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
				01 00 00 00
			)
			.override method instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
			// 方法起始 RVA 地址 0x2140
			// 方法起始地址(相对于文件绝对值:0x0340)
			// 代码长度 11 (0xb)
			.maxstack 1
			.locals init (
				[0] int32
			)

			// 0x034C: 02
			IL_0000: ldarg.0
			// 0x034D: 7B 01 00 00 04
			IL_0001: ldfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>2__current'
			// 0x0352: 0A
			IL_0006: stloc.0
			// 0x0353: 2B 00
			IL_0007: br.s IL_0009

			// 0x0355: 06
			IL_0009: ldloc.0
			// 0x0356: 2A
			IL_000a: ret
		} // 方法 '<InvokeYeid>d__0'::'System.Collections.Generic.IEnumerator<System.Int32>.get_Current' 结束

		.method private final hidebysig newslot virtual 
			instance void System.Collections.IEnumerator.Reset () cil managed 
		{
			.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
				01 00 00 00
			)
			.override method instance void [mscorlib]System.Collections.IEnumerator::Reset()
			// 方法起始 RVA 地址 0x2157
			// 方法起始地址(相对于文件绝对值:0x0357)
			// 代码长度 6 (0x6)
			.maxstack 8

			// 0x0358: 73 1A 00 00 0A
			IL_0000: newobj instance void [mscorlib]System.NotSupportedException::.ctor()
			// 0x035D: 7A
			IL_0005: throw
		} // 方法 '<InvokeYeid>d__0'::System.Collections.IEnumerator.Reset 结束

		.method private final hidebysig newslot virtual 
			instance void System.IDisposable.Dispose () cil managed 
		{
			.override method instance void [mscorlib]System.IDisposable::Dispose()
			// 方法起始 RVA 地址 0x215e
			// 方法起始地址(相对于文件绝对值:0x035e)
			// 代码长度 2 (0x2)
			.maxstack 8

			// 0x035F: 00
			IL_0000: nop
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x0360: 2A
			IL_0001: ret
		} // 方法 '<InvokeYeid>d__0'::System.IDisposable.Dispose 结束

		.method private final hidebysig specialname newslot virtual 
			instance object System.Collections.IEnumerator.get_Current () cil managed 
		{
			.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
				01 00 00 00
			)
			.override method instance object [mscorlib]System.Collections.IEnumerator::get_Current()
			// 方法起始 RVA 地址 0x2164
			// 方法起始地址(相对于文件绝对值:0x0364)
			// 代码长度 16 (0x10)
			.maxstack 1
			.locals init (
				[0] object
			)

			// 0x0370: 02
			IL_0000: ldarg.0
			// 0x0371: 7B 01 00 00 04
			IL_0001: ldfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>2__current'
			// 0x0376: 8C 1B 00 00 01
			IL_0006: box [mscorlib]System.Int32
			// 0x037B: 0A
			IL_000b: stloc.0
			// 0x037C: 2B 00
			IL_000c: br.s IL_000e

			// 0x037E: 06
			IL_000e: ldloc.0
			// 0x037F: 2A
			IL_000f: ret
		} // 方法 '<InvokeYeid>d__0'::System.Collections.IEnumerator.get_Current 结束

		.method public hidebysig specialname rtspecialname 
			instance void .ctor (
				int32 '<>1__state'
			) cil managed 
		{
			.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
				01 00 00 00
			)
			// 方法起始 RVA 地址 0x2180
			// 方法起始地址(相对于文件绝对值:0x0380)
			// 代码长度 25 (0x19)
			.maxstack 8

			// 0x0381: 02
			IL_0000: ldarg.0
			// 0x0382: 28 1B 00 00 0A
			IL_0001: call instance void [mscorlib]System.Object::.ctor()
			// 0x0387: 02
			IL_0006: ldarg.0
			// 0x0388: 03
			IL_0007: ldarg.1
			// 0x0389: 7D 02 00 00 04
			IL_0008: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>1__state'
			// 0x038E: 02
			IL_000d: ldarg.0
			// 0x038F: 28 19 00 00 0A
			IL_000e: call int32 [mscorlib]System.Environment::get_CurrentManagedThreadId()
			// 0x0394: 7D 03 00 00 04
			IL_0013: stfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>l__initialThreadId'
			// 0x0399: 2A
			IL_0018: ret
		} // 方法 '<InvokeYeid>d__0'::.ctor 结束

		// 属性
		.property instance int32 'System.Collections.Generic.IEnumerator<System.Int32>.Current'()
		{
			.get instance int32 YeidTest.Program/'<InvokeYeid>d__0'::'System.Collections.Generic.IEnumerator<System.Int32>.get_Current'()
		}
		.property instance object System.Collections.IEnumerator.Current()
		{
			.get instance object YeidTest.Program/'<InvokeYeid>d__0'::System.Collections.IEnumerator.get_Current()
		}

	} // 类 <InvokeYeid>d__0 结束


	// 方法
	.method public hidebysig static 
		class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> InvokeYeid () cil managed 
	{
		// 方法起始 RVA 地址 0x219c
		// 方法起始地址(相对于文件绝对值:0x039c)
		// 代码长度 14 (0xe)
		.maxstack 1
		.locals init (
			[0] class YeidTest.Program/'<InvokeYeid>d__0',
			[1] class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>
		)

		// 0x03A8: 1F FE
		IL_0000: ldc.i4.s -2
		// 0x03AA: 73 0B 00 00 06
		IL_0002: newobj instance void YeidTest.Program/'<InvokeYeid>d__0'::.ctor(int32)
		// 0x03AF: 0A
		IL_0007: stloc.0
		// 0x03B0: 06
		IL_0008: ldloc.0
		// 0x03B1: 0B
		IL_0009: stloc.1
		// 0x03B2: 2B 00
		IL_000a: br.s IL_000c

		// 0x03B4: 07
		IL_000c: ldloc.1
		// 0x03B5: 2A
		IL_000d: ret
	} // 方法 Program::InvokeYeid 结束

	.method private hidebysig static 
		void Main (
			string[] args
		) cil managed 
	{
		// 方法起始 RVA 地址 0x21b8
		// 方法起始地址(相对于文件绝对值:0x03b8)
		// 代码长度 292 (0x124)
		.maxstack 2
		.entrypoint
		.locals init (
			[0] int32 item,
			[1] class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> enumerator,
			[2] class [mscorlib]System.Collections.Generic.IEnumerator`1<int32> CS$5$0000,
			[3] bool CS$4$0001,
			[4] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32> CS$5$0002
		)

		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 19,列 9
		// 0x03C4: 00
		IL_0000: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 20,列 13
		// 0x03C5: 72 01 00 00 70
		IL_0001: ldstr "直接输出"
		// 0x03CA: 28 1C 00 00 0A
		IL_0006: call void [mscorlib]System.Console::WriteLine(string)
		// 0x03CF: 00
		IL_000b: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 21,列 13
		// 0x03D0: 28 01 00 00 06
		IL_000c: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> YeidTest.Program::InvokeYeid()
		// 0x03D5: 28 1D 00 00 0A
		IL_0011: call void [mscorlib]System.Console::WriteLine(object)
		// 0x03DA: 00
		IL_0016: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 23,列 13
		// 0x03DB: 72 0B 00 00 70
		IL_0017: ldstr "循环输出"
		// 0x03E0: 28 1C 00 00 0A
		IL_001c: call void [mscorlib]System.Console::WriteLine(string)
		// 0x03E5: 00
		IL_0021: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 24,列 13
		// 0x03E6: 00
		IL_0022: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 24,列 34
		// 0x03E7: 28 01 00 00 06
		IL_0023: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> YeidTest.Program::InvokeYeid()
		// 0x03EC: 6F 11 00 00 0A
		IL_0028: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
		// 0x03F1: 0C
		IL_002d: stloc.2
		.try
		{
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x03F2: 2B 1F
			IL_002e: br.s IL_004f
			// 循环开始 (head: IL_004f)
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 24,列 22
				// 0x03F4: 08
				IL_0030: ldloc.2
				// 0x03F5: 6F 14 00 00 0A
				IL_0031: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
				// 0x03FA: 0A
				IL_0036: stloc.0
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 25,列 13
				// 0x03FB: 00
				IL_0037: nop
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 26,列 17
				// 0x03FC: 06
				IL_0038: ldloc.0
				// 0x03FD: 8C 1B 00 00 01
				IL_0039: box [mscorlib]System.Int32
				// 0x0402: 72 15 00 00 70
				IL_003e: ldstr "  "
				// 0x0407: 28 1E 00 00 0A
				IL_0043: call string [mscorlib]System.String::Concat(object, object)
				// 0x040C: 28 1F 00 00 0A
				IL_0048: call void [mscorlib]System.Console::Write(string)
				// 0x0411: 00
				IL_004d: nop
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 27,列 13
				// 0x0412: 00
				IL_004e: nop

				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 24,列 31
				// 0x0413: 08
				IL_004f: ldloc.2
				// 0x0414: 6F 13 00 00 0A
				IL_0050: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
				// 0x0419: 0D
				IL_0055: stloc.3
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
				// 0x041A: 09
				IL_0056: ldloc.3
				// 0x041B: 2D D7
				IL_0057: brtrue.s IL_0030
			// 循环结束

			// 0x041D: DE 10
			IL_0059: leave.s IL_006b
		} // .try 结束
		finally
		{
			// 0x041F: 08
			IL_005b: ldloc.2
			// 0x0420: 14
			IL_005c: ldnull
			// 0x0421: FE 01
			IL_005d: ceq
			// 0x0423: 0D
			IL_005f: stloc.3
			// 0x0424: 09
			IL_0060: ldloc.3
			// 0x0425: 2D 07
			IL_0061: brtrue.s IL_006a

			// 0x0427: 08
			IL_0063: ldloc.2
			// 0x0428: 6F 16 00 00 0A
			IL_0064: callvirt instance void [mscorlib]System.IDisposable::Dispose()
			// 0x042D: 00
			IL_0069: nop

			// 0x042E: DC
			IL_006a: endfinally
		} // 捕捉结束

		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
		// 0x042F: 00
		IL_006b: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 29,列 13
		// 0x0430: 72 1B 00 00 70
		IL_006c: ldstr ""
		// 0x0435: 28 1C 00 00 0A
		IL_0071: call void [mscorlib]System.Console::WriteLine(string)
		// 0x043A: 00
		IL_0076: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 30,列 13
		// 0x043B: 72 1D 00 00 70
		IL_0077: ldstr "ToList后输出"
		// 0x0440: 28 1C 00 00 0A
		IL_007c: call void [mscorlib]System.Console::WriteLine(string)
		// 0x0445: 00
		IL_0081: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 33,列 13
		// 0x0446: 00
		IL_0082: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 33,列 34
		// 0x0447: 28 01 00 00 06
		IL_0083: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> YeidTest.Program::InvokeYeid()
		// 0x044C: 28 01 00 00 2B
		IL_0088: call class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
		// 0x0451: 6F 21 00 00 0A
		IL_008d: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<int32>::GetEnumerator()
		// 0x0456: 13 04
		IL_0092: stloc.s CS$5$0002
		.try
		{
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x0458: 2B 20
			IL_0094: br.s IL_00b6
			// 循环开始 (head: IL_00b6)
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 33,列 22
				// 0x045A: 12 04
				IL_0096: ldloca.s CS$5$0002
				// 0x045C: 28 22 00 00 0A
				IL_0098: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::get_Current()
				// 0x0461: 0A
				IL_009d: stloc.0
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 34,列 13
				// 0x0462: 00
				IL_009e: nop
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 35,列 17
				// 0x0463: 06
				IL_009f: ldloc.0
				// 0x0464: 8C 1B 00 00 01
				IL_00a0: box [mscorlib]System.Int32
				// 0x0469: 72 15 00 00 70
				IL_00a5: ldstr "  "
				// 0x046E: 28 1E 00 00 0A
				IL_00aa: call string [mscorlib]System.String::Concat(object, object)
				// 0x0473: 28 1F 00 00 0A
				IL_00af: call void [mscorlib]System.Console::Write(string)
				// 0x0478: 00
				IL_00b4: nop
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 36,列 13
				// 0x0479: 00
				IL_00b5: nop

				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 33,列 31
				// 0x047A: 12 04
				IL_00b6: ldloca.s CS$5$0002
				// 0x047C: 28 23 00 00 0A
				IL_00b8: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>::MoveNext()
				// 0x0481: 0D
				IL_00bd: stloc.3
				// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
				// 0x0482: 09
				IL_00be: ldloc.3
				// 0x0483: 2D D5
				IL_00bf: brtrue.s IL_0096
			// 循环结束

			// 0x0485: DE 0F
			IL_00c1: leave.s IL_00d2
		} // .try 结束
		finally
		{
			// 0x0487: 12 04
			IL_00c3: ldloca.s CS$5$0002
			// 0x0489: FE 16 04 00 00 1B
			IL_00c5: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32>
			// 0x048F: 6F 16 00 00 0A
			IL_00cb: callvirt instance void [mscorlib]System.IDisposable::Dispose()
			// 0x0494: 00
			IL_00d0: nop
			// 0x0495: DC
			IL_00d1: endfinally
		} // 捕捉结束

		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
		// 0x0496: 00
		IL_00d2: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 37,列 13
		// 0x0497: 72 1B 00 00 70
		IL_00d3: ldstr ""
		// 0x049C: 28 1C 00 00 0A
		IL_00d8: call void [mscorlib]System.Console::WriteLine(string)
		// 0x04A1: 00
		IL_00dd: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 38,列 13
		// 0x04A2: 72 31 00 00 70
		IL_00de: ldstr "直接通过迭代输出"
		// 0x04A7: 28 1C 00 00 0A
		IL_00e3: call void [mscorlib]System.Console::WriteLine(string)
		// 0x04AC: 00
		IL_00e8: nop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 40,列 13
		// 0x04AD: 28 01 00 00 06
		IL_00e9: call class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> YeidTest.Program::InvokeYeid()
		// 0x04B2: 6F 11 00 00 0A
		IL_00ee: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
		// 0x04B7: 0B
		IL_00f3: stloc.1
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
		// 0x04B8: 2B 1D
		IL_00f4: br.s IL_0113
		// 循环开始 (head: IL_0113)
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 42,列 13
			// 0x04BA: 00
			IL_00f6: nop
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 44,列 17
			// 0x04BB: 07
			IL_00f7: ldloc.1
			// 0x04BC: 6F 14 00 00 0A
			IL_00f8: callvirt instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
			// 0x04C1: 8C 1B 00 00 01
			IL_00fd: box [mscorlib]System.Int32
			// 0x04C6: 72 15 00 00 70
			IL_0102: ldstr "  "
			// 0x04CB: 28 1E 00 00 0A
			IL_0107: call string [mscorlib]System.String::Concat(object, object)
			// 0x04D0: 28 1F 00 00 0A
			IL_010c: call void [mscorlib]System.Console::Write(string)
			// 0x04D5: 00
			IL_0111: nop
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 45,列 13
			// 0x04D6: 00
			IL_0112: nop

			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 41,列 13
			// 0x04D7: 07
			IL_0113: ldloc.1
			// 0x04D8: 6F 13 00 00 0A
			IL_0114: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
			// 0x04DD: 0D
			IL_0119: stloc.3
			// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 16707566,列 0
			// 0x04DE: 09
			IL_011a: ldloc.3
			// 0x04DF: 2D D9
			IL_011b: brtrue.s IL_00f6
		// 循环结束

		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 47,列 13
		// 0x04E1: 28 24 00 00 0A
		IL_011d: call string [mscorlib]System.Console::ReadLine()
		// 0x04E6: 26
		IL_0122: pop
		// 文档: c:\Users\Administrator\Documents\Visual Studio 2012\Projects\YeidTest\YeidTest\Program.cs, 行 48,列 9
		// 0x04E7: 2A
		IL_0123: ret
	} // 方法 Program::Main 结束

	.method public hidebysig specialname rtspecialname 
		instance void .ctor () cil managed 
	{
		// 方法起始 RVA 地址 0x2304
		// 方法起始地址(相对于文件绝对值:0x0504)
		// 代码长度 7 (0x7)
		.maxstack 8

		// 0x0505: 02
		IL_0000: ldarg.0
		// 0x0506: 28 1B 00 00 0A
		IL_0001: call instance void [mscorlib]System.Object::.ctor()
		// 0x050B: 2A
		IL_0006: ret
	} // 方法 Program::.ctor 结束

} // 类 YeidTest.Program 结束


编译器自动实现了一个 《InvokeYeid》d__0
并在里面重写了 MoveNext() 和 Get_Current()

一、Console.WriteLine(InvokeYeid())
IL_000c: call class [mscorlib]System.Collections.Generic.IEnumerable`1 YeidTest.Program::InvokeYeid()
但是这个地方并没有输出值 而是输出了一个公式(方法 函数)
看看InvokeYeid() 的实现

.method public hidebysig static 
	class [mscorlib]System.Collections.Generic.IEnumerable`1<int32> InvokeYeid () cil managed 
{
	// 方法起始 RVA 地址 0x219c
	// 方法起始地址(相对于文件绝对值:0x039c)
	// 代码长度 14 (0xe)
	.maxstack 1
	.locals init (
		[0] class YeidTest.Program/'<InvokeYeid>d__0',
		[1] class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>
	)

	// 0x03A8: 1F FE
	IL_0000: ldc.i4.s -2   --将提供的 int8 值作为 int32 推送到计算堆栈上(短格式)。
	// 0x03AA: 73 0B 00 00 06
	IL_0002: newobj instance void YeidTest.Program/'<InvokeYeid>d__0'::.ctor(int32)
	--创建一个值类型的新对象或新实例,并将对象引用(O 类型)推送到计算堆栈上。
	// 0x03AF: 0A
	IL_0007: stloc.0 --从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。
	// 0x03B0: 06
	IL_0008: ldloc.0 --将索引 0 处的局部变量加载到计算堆栈上。
	// 0x03B1: 0B
	IL_0009: stloc.1  --从计算堆栈的顶部弹出当前值并将其存储到索引 1 处的局部变量列表中。
	// 0x03B2: 2B 00
	IL_000a: br.s IL_000c --无条件地将控制转移到目标指令 IL_000c

	// 0x03B4: 07
	IL_000c: ldloc.1	--将索引 1 处的局部变量加载到计算堆栈上。
	// 0x03B5: 2A
	IL_000d: ret		--从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
} // 方法 Program::InvokeYeid 结束

大致意思 就是 实例化了一个<InvokeYeid>d__0 ,并将“对象引用” (对象引用其实就是实例化对象所在的地址) 推送到计算堆栈上
然后把这个 “对象引用” 放入局部变量里面
然后返回这个局部变量
也就是说这个方式实际上 只返回了一个“对象引用”  而不是你想想中的 方法结果1 2 3

二、Console.Write(item + " ") 和 Console.Write(enumerator.Current + " ")
IL_0023: call class [mscorlib]System.Collections.Generic.IEnumerable`1 YeidTest.Program::InvokeYeid()

IL_0083: call class [mscorlib]System.Collections.Generic.IEnumerable`1 YeidTest.Program::InvokeYeid()

IL_00e9: call class [mscorlib]System.Collections.Generic.IEnumerable`1 YeidTest.Program::InvokeYeid()

也都分别调用了这个方法 唯一不同的是 这3个调用 在之后 都调用了
System.Collections.Generic.IEnumerator`1::get_Current() --获取当前对象
System.Collections.IEnumerator::MoveNext() --移动到下一个对象

这3个方法 都确实输出了 1 2 3

也就是说 实际执行是在get_Current() 和MoveNext() 才真正执行
MoveNext :我就不详细解释IL代码了 IEnumerator将枚举数推进到集合的下一个元素。

get_Current() :

	.method private final hidebysig specialname newslot virtual 
		instance int32 'System.Collections.Generic.IEnumerator<System.Int32>.get_Current' () cil managed 
	{
		.custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = (
			01 00 00 00
		)
		.override method instance !0 class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
		// 方法起始 RVA 地址 0x2140
		// 方法起始地址(相对于文件绝对值:0x0340)
		// 代码长度 11 (0xb)
		.maxstack 1
		.locals init (
			[0] int32
		)

		// 0x034C: 02
		IL_0000: ldarg.0     --将索引为 0 的参数加载到计算堆栈上。
		// 0x034D: 7B 01 00 00 04
		IL_0001: ldfld int32 YeidTest.Program/'<InvokeYeid>d__0'::'<>2__current'
		--查找对象中其引用当前位于计算堆栈的字段的值。 (很清楚了 获取对象引用的值 真正的执行)
		// 0x0352: 0A
		IL_0006: stloc.0 --从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。
		// 0x0353: 2B 00
		IL_0007: br.s IL_0009 --无条件跳转到 IL_0009 

		// 0x0355: 06
		IL_0009: ldloc.0  --将索引 0 处的局部变量加载到计算堆栈上。
		// 0x0356: 2A
		IL_000a: ret  	 --从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
	} // 方法 '<InvokeYeid>d__0'::'System.Collections.Generic.IEnumerator<System.Int32>.get_Current' 结束

简单来说 就是去的IEnumerator 先获取索引(下标)
然后在<InvokeYeid>d__0 根据索引(下标) 获取对应的值
返回这个值

这下非常清晰了
d__0 ,获得“对象引用”
然后通过get_Current() 获取值
并调用MoveNext() 把迭代数的this指针 指向下一个对象

扩展问题
.toLIst();迭代并把值返回给了List 所以调用了get_Current()从而实现了延迟加载 的真正调用

那么问题来了:
.First()
.FirstOrDefault()
.Singe()
.SingeOrDefault()

这几个方法呢

聪明的你想到了吧
一样啊 不过是迭代的时候 只获取了第一条记录 (然后根据不同的条件判断 输出了不同的结果而已)

这下我们可以用yeid 来做点好玩的东西了
扩展一个DbContext 来返回一个字典对象

 /// <summary>
        /// 返回动态查询
        /// 实际是Ienumerable<IDictionary<string, object>><dy>
        /// 延迟加载 只有在toList singleOrDealut fristOrDealut 等方法执行才会真真的加载使用
        /// </summary>
        /// <param name="db"></param>
        /// <param name="Sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static IEnumerable<dynamic> SqlQueryDynamic(this DbContext db, string Sql, params SqlParameter[] parameters)
        {
            using (var cmd = db.Database.Connection.CreateCommand())
            {
                cmd.CommandText = Sql;

                if (cmd.Connection.State != ConnectionState.Open)
                {
                    cmd.Connection.Open();
                }

                foreach (var p in parameters)
                {
                    var dbParameter = cmd.CreateParameter();
                    dbParameter.DbType = p.DbType;
                    dbParameter.ParameterName = p.ParameterName;
                    dbParameter.Value = p.Value;
                    cmd.Parameters.Add(dbParameter);
                }

                using (var dataReader = cmd.ExecuteReader())
                {
                    while (dataReader.Read())
                    {
                        //ExpandoObject 表示可在运行时动态添加和删除其成员的对象
                        var row = new ExpandoObject() as IDictionary<string, object>;
                        for (var fieldCount = 0; fieldCount < dataReader.FieldCount; fieldCount++)
                        {
                            row.Add(dataReader.GetName(fieldCount), dataReader[fieldCount]);
                        }
                        yield return row;
                    }
                }
            }
        }

接下来我们可以调用他了

void test(){
	houseEntities _wei = new houseEntities();
	var sql = 'select name,age from house c'
	var paramList = new List<SqlParamter>();
	var list = _wei.SqlQueryDynamic(sql, paramList.ToArray()).ToList();
	//这里返回的是一个动态对象IEnumerable<dynamic>
	foreachvar item in list ){
		console.write(item.name);
		console.write(item.age);
		//是不是很奇怪 item.name 这和普通过的写实体接受有啥区别
		//大爷的 你看到我写实体了?
		//是的我们通过这种方式 不写实体 也能使用EF了 和 延迟加载了
	}
}

如果你牛逼 ,你当然还能扩展
实现IEnumerable 的Where()方法 然后你可以
_wei.SqlQueryDynamic(sql, paramList.ToArray()).Where(“c.name = {0}” , “你大爷”)

好吧 今天就说道这了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值