事件和委託的區別到底是什麼
委託提供了一種機制,可實現涉及組件間最小耦合度的軟件設計,它是一種引用類型。
和委託類似,事件是後期綁定機制。事件是建立在對委託的語言支持之上的,它是對委託的封裝,可以理解爲一種特殊的委託(本質不是)。
事件是對象用於廣播已發生事情的一種方式。任何其他組件都可以訂閱事件,並在事件引發時得到通知。
相同點
- 它們都提供了一個後期綁定方案:在該方案中,組件通過調用僅在運行時識別的方法進行通信。
- 它們都支持單個和多個訂閱服務器方法。這稱爲單播和多播支持。
- 二者均支持用於添加和刪除處理程序的類似語法。
- 引發事件和調用委託使用完全相同的方法調用語法。它們甚至都支持與
?.
運算符一起使用的相同的Invoke()
方法語法。
不同點
- 用於事件的委託通常沒有返回值,如果需要返回值,那麼請使用委託。
- 對事件的偵聽是可選的。
- 事件只能從外部添加和刪除響應方法,不能主動觸發事件、獲取其它註冊的響應方法,而委託不受這種限制。
揭祕事件
一探究竟
在控制檯程序中定義一個事件OrderCompleted
internal class Program
{
/// <summary>
/// 訂單完成事件
/// </summary>
public event EventHandler OrderCompleted;
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
編譯下,通過ILSpy查看最終編譯代碼是什麼
// Fields
.field private class [System.Runtime]System.EventHandler OrderCompleted
.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [System.Diagnostics.Debug]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [System.Diagnostics.Debug]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
// Events
.event [System.Runtime]System.EventHandler OrderCompleted
{
.addon instance void demoForConsoleEvent31.Program::add_OrderCompleted(class [System.Runtime]System.EventHandler)
.removeon instance void demoForConsoleEvent31.Program::remove_OrderCompleted(class [System.Runtime]System.EventHandler)
}
實際上,它會編譯器編譯爲一個私有的屬性字段,並添加了addon和removeon兩個公開方法。
EventHandler是什麼
.class public auto ansi sealed System.EventHandler
extends System.MulticastDelegate
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method EventHandler::.ctor
...
}
我們看到,實際上System.EventHandler
擴展自System.MulticastDelegate
(多播委託),所以它本質就是委託。
而這個System.MulticastDelegate
又是什麼?我們進一步看看
.class public auto ansi abstract serializable beforefieldinit System.MulticastDelegate
extends System.Delegate
{
.custom instance void System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = (
01 00 01 00 00
)
// Fields
.field private object _invocationList
.field private native int _invocationCount
...
}
這不就是個委託類型System.Delegate
System.MulticastDelegate
(多播委託)相比System.Delegate
來說,具有一個帶有鏈接的委託列表(_invocationList
),稱爲調用列表,在對委託實例進行調用的時候,將按列表中的委託順序進行同步調用。
我們可以直接通過GetInvocationList
方法獲取到這個列表
Delegate[] list = OrderCompleted.GetInvocationList();
事件的本質
事件本質上,一組成對的Add/Remove的公開方法和一個包含委託類型對象(System.EventHandler
)的私有字段。
使用事件
public partial class Form1 : Form
{
/// <summary>
/// 訂單完成事件
/// </summary>
public event EventHandler OrderCompleted;
public Form1()
{
InitializeComponent();
OrderCompleted -= Form1_OnOrderCompleted;
OrderCompleted += Form1_OnOrderCompleted;
}
private void Form1_OnOrderCompleted(object sender, EventArgs e)
{
}
protected override void OnLoad(EventArgs e)
{
OrderCompleted.Invoke(this, e);
base.OnLoad(e);
}
}
通常來說,事件的處理程序通過以On
作爲前綴命名,後跟事件名稱。
其中-=
和+=
最終被編譯爲
// OrderCompleted -= Form1_OnOrderCompleted;
IL_0015: nop
IL_0016: ldarg.0
IL_0017: ldarg.0
IL_0018: ldftn instance void demoForFormEvent31.Form1::Form1_OrderCompleted(object, class [mscorlib]System.EventArgs)
IL_001e: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
IL_0023: call instance void demoForFormEvent31.Form1::remove_OrderCompleted(class [mscorlib]System.EventHandler)
// OrderCompleted += Form1_OnOrderCompleted;
IL_0028: nop
IL_0029: ldarg.0
IL_002a: ldarg.0
IL_002b: ldftn instance void demoForFormEvent31.Form1::Form1_OrderCompleted(object, class [mscorlib]System.EventArgs)
IL_0031: newobj instance void [mscorlib]System.EventHandler::.ctor(object, native int)
IL_0036: call instance void demoForFormEvent31.Form1::add_OrderCompleted(class [mscorlib]System.EventHandler)
實際上這裏是新建了一個System.EventHandler
類型的委託實例,和Form1_OnOrderCompleted
進行關聯,最終是響應了remove_OrderCompleted
和add_OrderCompleted
方法。
觸發事件
在OnLoad
方法中,我們對這個事件進行了一次觸發OrderCompleted.Invoke(this, e)
,我們看看最終變成了什麼
// this.OrderCompleted(this, e);
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.EventHandler demoForFormEvent31.Form1::OrderCompleted
IL_0007: ldarg.0
IL_0008: ldarg.1
IL_0009: callvirt instance void [mscorlib]System.EventHandler::Invoke(object, class [mscorlib]System.EventArgs)
實際上本質是,獲取了事件包含的System.EventHandler
類型委託,並調用了委託自帶的觸發方法Invoke
。
這裏OrderCompleted.Invoke(this, e)
其實最終變成了
namespace System
{
[Serializable]
[ComVisible(true)]
public delegate void EventHandler(object sender, EventArgs e);
}
事件參數
這裏我們設計到一個事件參數,名爲System.EventArgs
,看看它是什麼。
.class public auto ansi serializable beforefieldinit System.EventArgs
extends System.Object
{
.custom instance void System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = (
01 00 01 00 00
)
// Fields
.field public static initonly class System.EventArgs Empty
....
}
其本質也就是一個對象,類型是System.Object
。
揭祕委託
一探究竟
在控制檯程序中定義一個委託OrderOption
internal class Program
{
/// <summary>
/// 訂單選項委託
/// </summary>
public delegate void OrderOption();
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
編譯下,通過ILSpy查看最終編譯代碼是什麼
// Nested Types
.class nested public auto ansi sealed OrderOption
extends [System.Runtime]System.MulticastDelegate
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method OrderOption::.ctor
.method public hidebysig newslot virtual
instance void Invoke () runtime managed
{
} // end of method OrderOption::Invoke
.method public hidebysig newslot virtual
instance class [System.Runtime]System.IAsyncResult BeginInvoke (
class [System.Runtime]System.AsyncCallback callback,
object 'object'
) runtime managed
{
} // end of method OrderOption::BeginInvoke
.method public hidebysig newslot virtual
instance void EndInvoke (
class [System.Runtime]System.IAsyncResult result
) runtime managed
{
} // end of method OrderOption::EndInvoke
} // end of class OrderOption
首先我們看到OrderOption
是一個類(Class),其次它的基類是System.MulticastDelegate
(多播委託),這就證明其實委託本質是一個類,它是可以被實例化的。
並且它自帶三個方法:Invoke
、BeginInvoke
、EndInvoke
。
使用委託
前面清楚知道了委託其實本質是一個類,那我們使用它就先要將它實例化,再調用內部的方法。
/// <summary>
/// 訂單選項委託
/// </summary>
public delegate void OrderOption();
private void Form1_OrderCompleted(object sender, EventArgs e)
{
var orderOption = new OrderOption(InitOrderOption);
orderOption.Invoke();
}
public void InitOrderOption()
{
}
這裏實例化了一個OrderOption
,並且我們需要在構造函數這裏將參數傳進去,這裏我們構建了一個參數是InitOrderOption
方法,最後我們調用這個實例的Invoke
方法。
來看看這段代碼最終變成了啥
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
// {
IL_0000: nop
// OrderOption orderOption = InitOrderOption;
IL_0001: ldarg.0
IL_0002: ldftn instance void demoForFormEvent31.Form1::InitOrderOption()
IL_0008: newobj instance void demoForFormEvent31.Form1/OrderOption::.ctor(object, native int)
IL_000d: stloc.0
// orderOption();
IL_000e: ldloc.0
IL_000f: callvirt instance void demoForFormEvent31.Form1/OrderOption::Invoke()
// }
IL_0014: nop
IL_0015: ret
} // end of method Form1::Form1_OrderCompleted
.method public hidebysig
instance void InitOrderOption () cil managed
{
} // end of method Form1::InitOrderOption
可以看到,當我們通過構造函數將InitOrderOption
傳進去之後,它最終其實變成了一個基於InitOrderOption
創建一個新OrderOption
實例的動作。
然後Invoke
的時候確實是調用了OrderOption
實例內部的Invoke
方法。
使用匿名委託
我們知道委託我們還可以通過匿名方法(Anonymous Methods) 的方式來使用,匿名方法沒有名稱只有方法主體,可以寫成這樣
/// <summary>
/// 訂單選項委託
/// </summary>
public delegate void OrderOption();
private void Form1_OrderCompleted(object sender, EventArgs e)
{
OrderOption orderOption = delegate()
{
Console.WriteLine("123");
};
orderOption.Invoke();
}
看看最終它變成什麼樣子了
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
IL_0000: nop
// OrderOption orderOption = delegate
// {
// Console.WriteLine("123");
// };
IL_0001: ldsfld class demoForFormEvent31.Form1/OrderOption demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0006: dup
IL_0007: brtrue.s IL_0020
// (no C# code)
IL_0009: pop
// orderOption();
IL_000a: ldsfld class demoForFormEvent31.Form1/'<>c' demoForFormEvent31.Form1/'<>c'::'<>9'
IL_000f: ldftn instance void demoForFormEvent31.Form1/'<>c'::'<Form1_OrderCompleted>b__5_0'()
IL_0015: newobj instance void demoForFormEvent31.Form1/OrderOption::.ctor(object, native int)
IL_001a: dup
IL_001b: stsfld class demoForFormEvent31.Form1/OrderOption demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0020: stloc.0
IL_0021: ldloc.0
IL_0022: callvirt instance void demoForFormEvent31.Form1/OrderOption::Invoke()
// }
IL_0027: nop
IL_0028: ret
} // end of method Form1::Form1_OrderCompleted
實際上它也是實例化了一個OrderOption
並調用了它Invoke
方法。
這樣寫,這個函數沒有名字,但是這個委託需要有個明確的名字。
使用Lamada簡寫匿名委託
在C#中,我們可以使用Lambda表達式來創建匿名函數。Lambda表達式的左側是輸入參數,中間符號是=>
,右側是匿名函數的主體。
通常可以寫成,其中$Input Params
可以沒有:
($Input Params) => $Expression;
// 或者
($Input Params) => { };
private void Form1_OrderCompleted(object sender, EventArgs e)
{
OrderOption orderOption = () =>
{
Console.WriteLine("123");
};
orderOption.Invoke();
}
看看最終它變成什麼樣子了
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
IL_0000: nop
// OrderOption orderOption = delegate
// {
// Console.WriteLine("123");
// };
IL_0001: ldsfld class demoForFormEvent31.Form1/OrderOption demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0006: dup
IL_0007: brtrue.s IL_0020
// (no C# code)
IL_0009: pop
// orderOption();
IL_000a: ldsfld class demoForFormEvent31.Form1/'<>c' demoForFormEvent31.Form1/'<>c'::'<>9'
IL_000f: ldftn instance void demoForFormEvent31.Form1/'<>c'::'<Form1_OrderCompleted>b__5_0'()
IL_0015: newobj instance void demoForFormEvent31.Form1/OrderOption::.ctor(object, native int)
IL_001a: dup
IL_001b: stsfld class demoForFormEvent31.Form1/OrderOption demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0020: stloc.0
IL_0021: ldloc.0
IL_0022: callvirt instance void demoForFormEvent31.Form1/OrderOption::Invoke()
// }
IL_0027: nop
IL_0028: ret
} // end of method Form1::Form1_OrderCompleted
這裏我們看到其本質和前面使用匿名函數是一模一樣的,Lambda表達式實際上創造匿名函數的一個語法糖。
使用Func泛型委託
我們知道,通過Func可以構建帶返回值的泛型委託。
private void Form1_OrderCompleted(object sender, EventArgs e)
{
Func<int,int,int> orderSum = (x, y) =>
{
return x + y;
};
Console.WriteLine(orderSum);
}
Func的用法是,最後一個參數是返回值類型,前面的參數是輸入參數的類型。
看看最後編譯成啥樣
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
// {
IL_0000: nop
// Func<int, int, int> func = (int x, int y) => x + y;
IL_0001: ldsfld class [mscorlib]System.Func`3<int32, int32, int32> demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0006: dup
IL_0007: brtrue.s IL_0020
// (no C# code)
IL_0009: pop
// func(1, 2);
IL_000a: ldsfld class demoForFormEvent31.Form1/'<>c' demoForFormEvent31.Form1/'<>c'::'<>9'
IL_000f: ldftn instance int32 demoForFormEvent31.Form1/'<>c'::'<Form1_OrderCompleted>b__5_0'(int32, int32)
IL_0015: newobj instance void class [mscorlib]System.Func`3<int32, int32, int32>::.ctor(object, native int)
IL_001a: dup
IL_001b: stsfld class [mscorlib]System.Func`3<int32, int32, int32> demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0020: stloc.0
IL_0021: ldloc.0
IL_0022: ldc.i4.1
IL_0023: ldc.i4.2
IL_0024: callvirt instance !2 class [mscorlib]System.Func`3<int32, int32, int32>::Invoke(!0, !1)
IL_0029: pop
// }
IL_002a: ret
} // end of method Form1::Form1_OrderCompleted
它最終等價於
Func<int, int, int> func = (int x, int y) => x + y;
其中System.Func
的定義,發現它也是基於System.MulticastDelegate
多播委託的。
.class public auto ansi sealed System.Func`3<-T1, -T2, +TResult>
extends System.MulticastDelegate
{
.custom instance void System.Runtime.CompilerServices.TypeForwardedFromAttribute::.ctor(string) = (
01 00 4e 53 79 73 74 65 6d 2e 43 6f 72 65 2c 20
56 65 72 73 69 6f 6e 3d 33 2e 35 2e 30 2e 30 2c
20 43 75 6c 74 75 72 65 3d 4e 65 75 74 72 61 6c
2c 20 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e
3d 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38
39 00 00
)
.custom instance void __DynamicallyInvokableAttribute::.ctor() = (
01 00 00 00
)
...
} // end of class System.Func`3
使用Action泛型委託
我們知道,通過Action可以構建無返回值的泛型委託。
private void Form1_OrderCompleted(object sender, EventArgs e)
{
Action<int, int> orderSum = (x, y) =>
{
Console.WriteLine(x + y);
};
orderSum.Invoke(1,2);
}
Action的用法是,參數是輸入參數的類型,無法返回返回值,其構建的匿名函數都是Void的。
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
// {
IL_0000: nop
// Action<int, int> action = delegate(int x, int y)
// {
// Console.WriteLine(x + y);
// };
IL_0001: ldsfld class [mscorlib]System.Action`2<int32, int32> demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0006: dup
IL_0007: brtrue.s IL_0020
// (no C# code)
IL_0009: pop
// action(1, 2);
IL_000a: ldsfld class demoForFormEvent31.Form1/'<>c' demoForFormEvent31.Form1/'<>c'::'<>9'
IL_000f: ldftn instance void demoForFormEvent31.Form1/'<>c'::'<Form1_OrderCompleted>b__5_0'(int32, int32)
IL_0015: newobj instance void class [mscorlib]System.Action`2<int32, int32>::.ctor(object, native int)
IL_001a: dup
IL_001b: stsfld class [mscorlib]System.Action`2<int32, int32> demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0020: stloc.0
IL_0021: ldloc.0
IL_0022: ldc.i4.1
IL_0023: ldc.i4.2
IL_0024: callvirt instance void class [mscorlib]System.Action`2<int32, int32>::Invoke(!0, !1)
// }
IL_0029: nop
IL_002a: ret
} // end of method Form1::Form1_OrderCompleted
它最終等價於
Action<int, int> action = delegate(int x, int y)
{
Console.WriteLine(x + y);
};
其中System.Action
的定義,發現它也是基於System.MulticastDelegate
多播委託的。
.class public auto ansi sealed System.Action`2<-T1, -T2>
extends System.MulticastDelegate
{
.custom instance void System.Runtime.CompilerServices.TypeForwardedFromAttribute::.ctor(string) = (
01 00 4e 53 79 73 74 65 6d 2e 43 6f 72 65 2c 20
56 65 72 73 69 6f 6e 3d 33 2e 35 2e 30 2e 30 2c
20 43 75 6c 74 75 72 65 3d 4e 65 75 74 72 61 6c
2c 20 50 75 62 6c 69 63 4b 65 79 54 6f 6b 65 6e
3d 62 37 37 61 35 63 35 36 31 39 33 34 65 30 38
39 00 00
)
.custom instance void __DynamicallyInvokableAttribute::.ctor() = (
01 00 00 00
)
} // end of class System.Action`2
揭祕匿名類型
什麼是匿名類型
匿名類型提供了一種方便的方法,可用來將一組只讀屬性封裝到單個對象中,而無需首先顯式定義一個類型。類型名由編譯器生成,並且不能在源代碼級使用。每個屬性的類型由編譯器推斷。
通過關鍵詞var
可以接收一個匿名類型,實際上並不出來這種類型,它不會是編譯器提供的一個障眼法,本質是,編輯器幫忙從後面的賦值語句推薦了類型。
使用匿名類型
這裏構建了多種形式的匿名類型使用案例,它們都用過var
來進行接收。
private void Form1_OrderCompleted(object sender, EventArgs e)
{
var v = new { Amount = 108, Message = "Hello" };
var x = 1;
var y = 2;
var order = new Order();
var orderSum = (int x, int y) =>
{
Console.WriteLine(x + y);
};
orderSum.Invoke(x, y);
}
編譯之後的樣子。
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
// {
IL_0000: nop
// var anon = new
// {
// Amount = 108,
// Message = "Hello"
// };
IL_0001: ldc.i4.s 108
IL_0003: ldstr "Hello"
IL_0008: newobj instance void class '<>f__AnonymousType0`2'<int32, string>::.ctor(!0, !1)
IL_000d: stloc.0
// int arg = 1;
IL_000e: ldc.i4.1
IL_000f: stloc.1
// int arg2 = 2;
IL_0010: ldc.i4.2
IL_0011: stloc.2
// Order order = new Order();
IL_0012: newobj instance void demoForFormEvent31.Form1/Order::.ctor()
IL_0017: stloc.3
// Action<int, int> action = delegate(int x, int y)
// {
// Console.WriteLine(x + y);
// };
IL_0018: ldsfld class [mscorlib]System.Action`2<int32, int32> demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_001d: dup
IL_001e: brtrue.s IL_0037
// (no C# code)
IL_0020: pop
// action(arg, arg2);
IL_0021: ldsfld class demoForFormEvent31.Form1/'<>c' demoForFormEvent31.Form1/'<>c'::'<>9'
IL_0026: ldftn instance void demoForFormEvent31.Form1/'<>c'::'<Form1_OrderCompleted>b__5_0'(int32, int32)
IL_002c: newobj instance void class [mscorlib]System.Action`2<int32, int32>::.ctor(object, native int)
IL_0031: dup
IL_0032: stsfld class [mscorlib]System.Action`2<int32, int32> demoForFormEvent31.Form1/'<>c'::'<>9__5_0'
IL_0037: stloc.s 4
IL_0039: ldloc.s 4
IL_003b: ldloc.1
IL_003c: ldloc.2
IL_003d: callvirt instance void class [mscorlib]System.Action`2<int32, int32>::Invoke(!0, !1)
// }
IL_0042: nop
IL_0043: ret
} // end of method Form1::Form1_OrderCompleted
我們看到,var v = new { Amount = 108, Message = "Hello" };
實際上是被創建了一個類型爲AnonymousType
的對象。
.class private auto ansi sealed beforefieldinit '<>f__AnonymousType0`2'<'<Amount>j__TPar', '<Message>j__TPar'>
extends [mscorlib]System.Object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerDisplayAttribute::.ctor(string) = (
01 00 2b 5c 7b 20 41 6d 6f 75 6e 74 20 3d 20 7b
41 6d 6f 75 6e 74 7d 2c 20 4d 65 73 73 61 67 65
20 3d 20 7b 4d 65 73 73 61 67 65 7d 20 7d 01 00
54 0e 04 54 79 70 65 10 3c 41 6e 6f 6e 79 6d 6f
75 73 20 54 79 70 65 3e
)
}
它基於System.Object
的。
其他的,因爲右側都有明確的類型可以推斷,所以編譯器都編譯爲了具體的類型。
int arg = 1;
int arg2 = 2;
Order order = new Order();
Action<int, int> action = delegate(int x, int y)
{
Console.WriteLine(x + y);
};
使用Linq查詢表達式
LINQ查詢表達式模式依賴於其所有功能的委託。
創建LINQ查詢時,爲此特定目的提供委託的實現。
public class Order
{
public int Id { get; set; }
}
private void Form1_OrderCompleted(object sender, EventArgs e)
{
var orders = new List<Order>();
var smallNumbers = orders.Where(n => n.Id < 10);
}
編譯後的結果
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
// {
IL_0000: nop
// List<Order> source = new List<Order>();
IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<class demoForFormEvent31.Form1/Order>::.ctor()
IL_0006: stloc.0
// IEnumerable<Order> enumerable = source.Where((Order n) => n.Id < 10);
IL_0007: ldloc.0
IL_0008: ldsfld class [mscorlib]System.Func`2<class demoForFormEvent31.Form1/Order, bool> demoForFormEvent31.Form1/'<>c'::'<>9__6_0'
IL_000d: dup
IL_000e: brtrue.s IL_0027
// }
IL_0010: pop
IL_0011: ldsfld class demoForFormEvent31.Form1/'<>c' demoForFormEvent31.Form1/'<>c'::'<>9'
IL_0016: ldftn instance bool demoForFormEvent31.Form1/'<>c'::'<Form1_OrderCompleted>b__6_0'(class demoForFormEvent31.Form1/Order)
IL_001c: newobj instance void class [mscorlib]System.Func`2<class demoForFormEvent31.Form1/Order, bool>::.ctor(object, native int)
IL_0021: dup
IL_0022: stsfld class [mscorlib]System.Func`2<class demoForFormEvent31.Form1/Order, bool> demoForFormEvent31.Form1/'<>c'::'<>9__6_0'
IL_0027: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Where<class demoForFormEvent31.Form1/Order>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [mscorlib]System.Func`2<!!0, bool>)
IL_002c: stloc.1
IL_002d: ret
} // end of method Form1::Form1_OrderCompleted
它等價於
List<Order> source = new List<Order>();
IEnumerable<Order> enumerable = source.Where((Order n) => n.Id < 10);
處理NULL委託
在觸發委託之前,我們最好先要確定下觸發的這個委託是否爲Null,一般使用?
寫成
private void Form1_OrderCompleted(object sender, EventArgs e)
{
var orderOption = new OrderOption(InitOrderOption);
orderOption?.Invoke();
}
.method private hidebysig
instance void Form1_OrderCompleted (
object sender,
class [mscorlib]System.EventArgs e
) cil managed
{
// {
IL_0000: nop
// new OrderOption(InitOrderOption)?.Invoke();
IL_0001: ldarg.0
IL_0002: ldftn instance void demoForFormEvent31.Form1::InitOrderOption()
IL_0008: newobj instance void demoForFormEvent31.Form1/OrderOption::.ctor(object, native int)
IL_000d: stloc.0
// }
IL_000e: ldloc.0
IL_000f: brtrue.s IL_0013
IL_0011: br.s IL_001a
// (no C# code)
IL_0013: ldloc.0
IL_0014: callvirt instance void demoForFormEvent31.Form1/OrderOption::Invoke()
IL_0019: nop
IL_001a: ret
} // end of method Form1::Form1_OrderCompleted