.NET?Core?委托原理解析(最新推薦)
在 .NET Core 中,委托(Delegate)是一種類型安全的函數(shù)指針,它允許你將方法作為參數(shù)傳遞給其他方法,或者將方法存儲(chǔ)在變量中以便稍后調(diào)用。委托在事件處理、回調(diào)機(jī)制以及異步編程中非常有用。理解委托的運(yùn)行原理對于掌握 .NET Core 的高級編程技巧至關(guān)重要。
1. 委托的基本概念
委托是一種引用類型,它引用一個(gè)或多個(gè)方法。委托定義了方法的簽名(參數(shù)類型和返回類型),因此只有具有相同簽名的方法才能被委托引用。
1.1 定義委托
你可以通過 delegate 關(guān)鍵字來定義一個(gè)委托類型。例如:
// 定義一個(gè)委托類型 public delegate void GreetDelegate(string name);
這個(gè)委托類型 GreetDelegate 可以引用任何具有 void 返回類型和 string 參數(shù)的方法。
1.2 實(shí)例化委托
一旦定義了委托類型,你可以創(chuàng)建該委托的實(shí)例,并將方法賦值給它。例如:
// 與委托簽名匹配的方法
public void Greet(string name)
{
Console.WriteLine($"Hello, {name}!");
}
// 創(chuàng)建委托實(shí)例并綁定方法
GreetDelegate del = new GreetDelegate(Greet);在這個(gè)例子中,del 是一個(gè)委托實(shí)例,它引用了 Greet 方法。
1.3 調(diào)用委托
你可以像調(diào)用方法一樣調(diào)用委托:
// 調(diào)用委托
del("World");這會(huì)調(diào)用 del 方法,并輸出 "Hello, World!"。
2.委托的類型
1. 單播委托(Singlecast Delegate)
單播委托是指一個(gè)委托實(shí)例只能引用一個(gè)方法。這是最基本的委托類型。
public delegate void GreetDelegate(string message);
public void ShowMessage(string message)
{
Console.WriteLine(message);
}
GreetDelegate del = new GreetDelegate(ShowMessage);
del("Hello, World!"); // 輸出:Hello, World!2. 多播委托(Multicast Delegate)
多播委托是指一個(gè)委托實(shí)例可以引用多個(gè)方法。通過 += 運(yùn)算符可以將多個(gè)方法添加到委托實(shí)例中,并通過 -= 運(yùn)算符移除方法。
public void ShowMessage1(string message)
{
Console.WriteLine($"Message 1: {message}");
}
public void ShowMessage2(string message)
{
Console.WriteLine($"Message 2: {message}");
}
public void ShowMessage3(string message)
{
Console.WriteLine($"Message 3: {message}");
}
GreetMulticastDelegate del = new GreetMulticastDelegate(ShowMessage1);
del += ShowMessage2;
del += ShowMessage3;
del -= ShowMessage2;
del("Hello, World!");在這個(gè)例子中,del 委托實(shí)例引用了多個(gè)方法:將ShowMessage1,ShowMessage2 和 ShowMessage3添加到了多播委托實(shí)例中,然后并通過 -= 運(yùn)算符移除ShowMessage2。然后調(diào)用 del("Hello, World!") 時(shí),三個(gè)方法都會(huì)被調(diào)用,輸出如下:
Message 1: Hello, World! //ShowMessage2方法已移除 Message 3: Hello, World!
3. 泛型委托(Generic Delegate)
泛型委托是 C# 中的一種特殊委托類型,它允許你定義可以處理多種數(shù)據(jù)類型的委托。通過使用泛型,你可以編寫更通用、更靈活的代碼,而不需要為每種數(shù)據(jù)類型單獨(dú)定義委托。
以下是幾個(gè)泛型委托的示例,展示了如何使用泛型委托處理不同類型的數(shù)據(jù)。
3.1 簡單的泛型委托
public delegate T MyGenericDelegate<T>(T arg);
public int Square(int x)
{
return x * x;
}
public string Reverse(string s)
{
return new string(s.Reverse().ToArray());
}
MyGenericDelegate<int> intDelegate = new MyGenericDelegate<int>(Square);
Console.WriteLine(intDelegate(5)); // 輸出:25
MyGenericDelegate<string> stringDelegate = new MyGenericDelegate<string>(Reverse);
Console.WriteLine(stringDelegate("hello")); // 輸出:olleh- • 說明:
- •
MyGenericDelegate實(shí)例化了一個(gè)處理int類型數(shù)據(jù)的委托。 - •
MyGenericDelegate實(shí)例化了一個(gè)處理string類型數(shù)據(jù)的委托。
- •
3.2 多參數(shù)泛型委托
public delegate TResult MyGenericDelegate<T1, T2, TResult>(T1 arg1, T2 arg2);
public int Add(int a, int b)
{
return a + b;
}
public string Concat(string s1, string s2)
{
return s1 + s2;
}
MyGenericDelegate<int, int, int> intDelegate = new MyGenericDelegate<int, int, int>(Add);
Console.WriteLine(intDelegate(3, 5)); // 輸出:8
MyGenericDelegate<string, string, string> stringDelegate = new MyGenericDelegate<string, string, string>(Concat);
Console.WriteLine(stringDelegate("Hello, ", "World!")); // 輸出:Hello, World!- • 說明:
- •
MyGenericDelegate實(shí)例化了一個(gè)處理兩個(gè)int類型參數(shù)并返回int類型結(jié)果的委托。 - •
MyGenericDelegate實(shí)例化了一個(gè)處理兩個(gè)string類型參數(shù)并返回string類型結(jié)果的委托。
- •
4. 內(nèi)置委托類型
C# 提供了一些內(nèi)置的泛型委托類型,可以直接使用,而無需自定義委托。
4.1 Action 委托
Action 委托用于引用沒有返回值的方法。它可以有 0 到 16 個(gè)參數(shù)。
Action<string> action = (message) => Console.WriteLine(message);
action("Hello, World!"); // 輸出:Hello, World!4.2 Func 委托
Func 委托用于引用有返回值的方法。它可以有 0 到 16 個(gè)參數(shù),最后一個(gè)泛型參數(shù)是返回值類型。
Func<int, int, int> add = (a, b) => a + b; Console.WriteLine(add(3, 5)); // 輸出:8
4.3 Predicate 委托
Predicate 委托用于引用返回布爾值的方法,通常用于條件判斷。
Predicate<int> isEven = (num) => num % 2 == 0; Console.WriteLine(isEven(4)); // 輸出:True
5. 匿名方法委托
匿名方法允許你直接定義委托的實(shí)現(xiàn),而無需顯式聲明一個(gè)方法。
MyDelegate del = delegate(string message)
{
Console.WriteLine(message);
};
del("Hello, World!"); // 輸出:Hello, World!6. Lambda 表達(dá)式委托
Lambda 表達(dá)式是一種更簡潔的匿名方法寫法,通常用于定義委托。
Action<string> action = (message) => Console.WriteLine(message);
action("Hello, World!"); // 輸出:Hello, World!
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 5)); // 輸出:87. 事件委托
事件是一種特殊的委托,通常用于實(shí)現(xiàn)觀察者模式。事件委托通常與 EventHandler 或 EventHandler 一起使用。
public class Button
{
public event EventHandler Click;
public void OnClick()
{
Click?.Invoke(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main()
{
Button button = new Button();
button.Click += (sender, e) => Console.WriteLine("Button clicked!");
button.OnClick(); // 輸出:Button clicked!
}
}8. 異步委托
異步委托允許你異步調(diào)用方法,通常與 BeginInvoke 和 EndInvoke 一起使用。
public delegate int MyAsyncDelegate(int x, int y);
public int Add(int a, int b)
{
return a + b;
}
MyAsyncDelegate del = new MyAsyncDelegate(Add);
IAsyncResult result = del.BeginInvoke(3, 5, null, null);
int sum = del.EndInvoke(result);
Console.WriteLine(sum); // 輸出:89. 動(dòng)態(tài)委托
動(dòng)態(tài)委托允許你在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建和調(diào)用委托。
public int Multiply(int a, int b)
{
return a * b;
}
var method = typeof(Program).GetMethod("Multiply");
var del = Delegate.CreateDelegate(typeof(Func<int, int, int>), null, method);
int result = (del as Func<int, int, int>)(3, 5);
Console.WriteLine(result); // 輸出:153. 委托的運(yùn)行原理
委托的運(yùn)行原理涉及到 .NET Core 的運(yùn)行時(shí)機(jī)制和內(nèi)部實(shí)現(xiàn)。以下是委托運(yùn)行原理的關(guān)鍵點(diǎn):
3.1 委托的內(nèi)部結(jié)構(gòu)
在 .NET Core 中,委托是一個(gè)類,它繼承自 System.MulticastDelegate 類。System.MulticastDelegate 類又繼承自 System.Delegate 類。委托類包含以下關(guān)鍵成員:
- •
_target:指向調(diào)用方法的對象實(shí)例(如果是靜態(tài)方法,則為null)。 - •
_methodPtr:指向方法的函數(shù)指針。 - •
_invocationList:用于存儲(chǔ)多播委托中的多個(gè)方法。
3.2 委托的調(diào)用
當(dāng)你調(diào)用委托時(shí),.NET Core 運(yùn)行時(shí)會(huì)執(zhí)行以下步驟:
- 1. 檢查委托實(shí)例是否為****
**null**:如果委托實(shí)例為null,則會(huì)拋出NullReferenceException。 - 2. 調(diào)用委托的****
**Invoke******方法:委托實(shí)例的Invoke方法會(huì)被調(diào)用,該方法會(huì)根據(jù)_target和_methodPtr調(diào)用實(shí)際的方法。 - 3. 處理多播委托:如果委托是多播委托(即
_invocationList不為null),則Invoke方法會(huì)遍歷_invocationList,依次調(diào)用每個(gè)方法。
3.3 委托的優(yōu)化
.NET Core 對委托的調(diào)用進(jìn)行了優(yōu)化,以提高性能。例如,對于單播委托(即只引用一個(gè)方法的委托),.NET Core 會(huì)直接調(diào)用方法,而不需要通過 Invoke 方法。
4. 委托的應(yīng)用場景
委托在 .NET Core 中有多種應(yīng)用場景,以下是一些常見的場景:
4.1 事件處理
委托在事件處理中非常常見。事件是一種特殊的委托,它允許對象在發(fā)生某些事情時(shí)通知其他對象。例如:
C#public class Button
{
public event Action Click;
public void OnClick()
{
Click?.Invoke();
}
}
public class Program
{
public static void Main()
{
Button button = new Button();
button.Click += () => Console.WriteLine("Button clicked!");
button.OnClick();
}
}在這個(gè)例子中,Button 類定義了一個(gè) Click 事件,當(dāng) OnClick 方法被調(diào)用時(shí),事件處理程序會(huì)被觸發(fā)。
4.2 回調(diào)機(jī)制
委托可以用于實(shí)現(xiàn)回調(diào)機(jī)制,允許一個(gè)方法在完成時(shí)通知另一個(gè)方法。例如:
public void DoWork(Action callback)
{
// 執(zhí)行一些工作
Console.WriteLine("Work is done.");
// 調(diào)用回調(diào)方法
callback?.Invoke();
}
public void Main()
{
DoWork(() => Console.WriteLine("Callback called."));
}在這個(gè)例子中,DoWork 方法在完成工作后調(diào)用傳入的回調(diào)方法。
4.3 異步編程
委托在異步編程中也非常有用。例如,Task 類的 ContinueWith 方法允許你在任務(wù)完成時(shí)執(zhí)行一個(gè)委托:
Task.Run(() => Console.WriteLine("Task is running..."))
.ContinueWith(task => Console.WriteLine("Task is completed."));5. 總結(jié)
委托是 .NET Core 中一個(gè)非常強(qiáng)大的特性,它允許你將方法作為參數(shù)傳遞、存儲(chǔ)和調(diào)用。理解委托的運(yùn)行原理有助于你更好地利用這一特性,特別是在事件處理、回調(diào)機(jī)制和異步編程中。通過掌握委托,你可以編寫更加靈活和可擴(kuò)展的代碼。
到此這篇關(guān)于.NET Core 委托原理解析的文章就介紹到這了,更多相關(guān).NET Core 委托原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
asp.net MVC實(shí)現(xiàn)簡單的上傳功能
MVC中上傳變得越來越容易,可是對于新手這個(gè)也還是不知道如何實(shí)現(xiàn),以下方式實(shí)現(xiàn)MVC的上傳功能,以下2種方法都是可以實(shí)現(xiàn)的,其中的代碼參考了藍(lán)色小鋪和重典的文章。2009-11-11
Ext.net中的MessageBox的簡單應(yīng)用實(shí)現(xiàn)代碼
今天在項(xiàng)目中要用到簡單的MessageBox的使用。在Ext.net中沒有Winform那么簡單,直接寫MessageBox.show()的方法。于是就去examples.ext.net的例子網(wǎng)站找,想找到個(gè)實(shí)際能用的2012-03-03
.NET?SkiaSharp?生成二維碼驗(yàn)證碼及指定區(qū)域截取方法實(shí)現(xiàn)
這篇文章主要為大家介紹了.NET?SkiaSharp?生成二維碼驗(yàn)證碼及指定區(qū)域截取方法實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
ASP.NET獲取MS SQL Server安裝實(shí)例實(shí)現(xiàn)思路及代碼
在演示中,是把找到的實(shí)例顯示于DropDownList控件中。首先在.aspx拉一個(gè)DropDownList控件,感興趣的朋友可以了解下哦,或許對你有所幫助2013-01-01
Asp.net中Response.Charset與Response.ContentEncoding區(qū)別示例分析
這篇文章主要介紹了Asp.net中Response.Charset與Response.ContentEncoding區(qū)別示例分析,對于深入理解Asp.net程序設(shè)計(jì)有一定的幫助,需要的朋友可以參考下2014-08-08
Microsoft Visual Studio 2010下如何添加命令提示行
這篇文章主要介紹了Microsoft Visual Studio 2010下如何添加命令提示行的相關(guān)資料,需要的朋友可以參考下2015-11-11
ASP.NET實(shí)現(xiàn)讀取Excel內(nèi)容并在Web上顯示
這篇文章主要介紹了ASP.NET實(shí)現(xiàn)讀取Excel內(nèi)容并在Web上顯示,很實(shí)用的一個(gè)技巧,需要的朋友可以參考下2014-08-08

