c#委托詳解和和示例分享
委托是尋址方法的.NET版本,使用委托可以將方法作為參數(shù)進行傳遞。委托是一種特殊類型的對象,其特殊之處在于委托中包含的只是一個活多個方法的地址,而不是數(shù)據(jù)。
委托雖然看起來像是一種類型,但其實定義一個委托,是定義了一個新的類。下面這行代碼,定義了一個委托,使用ILDasm.exe查看其生成的IL代碼如圖所示:
//定義委托,它定義了可以代表的方法的類型,但其本身卻是一個類
public delegate int methodDelegate(string str);
由圖中紅色框線中可以看出,.NET將委托定義為一個密封類,派生自基類System.MulticastDelegate,并繼承了基類的三個方法(稍后討論這三個)。
委托與函數(shù)指針的區(qū)別1、安全性:C/C++的函數(shù)指針只是提取了函數(shù)的地址,并作為一個參數(shù)傳遞它,沒有類型安全性,可以把任何函數(shù)傳遞給需要函數(shù)指針的地方;而.NET中的委托是類型安全的。
2、與實例的關(guān)聯(lián)性:在面向?qū)ο缶幊讨?,幾乎沒有方法是孤立存在的,而是在調(diào)用方法前通常需要與類實例相關(guān)聯(lián)。委托可以獲取到類實例中的信息,從而實現(xiàn)與實例的關(guān)聯(lián)。
3、本質(zhì)上函數(shù)指針是一個指針變量,分配在棧中;委托類型聲明的是一個類,實例化為一個對象,分配在堆中。
4、委托可以指向不同類中具有相同參數(shù)和簽名的函數(shù),函數(shù)指針則不可以。
namespace ConsoleApplication1
{
//定義委托,它定義了可以代表的方法的類型,但其本身卻是一個類
public delegate void methodDelegate(string str);
class Program
{
static void Main(string[] args)
{
Student student = new Student();
Teacher teacher = new Teacher("王老師");
methodDelegate methodDelegate1 = new methodDelegate(student.getStudentName);
methodDelegate1 += teacher.getTeacherName; //可以指向不同類中的方法!
//methodDelegate1 += teacher.getClassName; 指向簽名不符的方法時提示錯誤!
methodDelegate1.Invoke("張三");
Console.ReadLine();
}
}
class Student
{
private String name = "";
public Student (String _name)
{
this.name = _name ;
}
public Student() {}
public void getStudentName(String _name)
{
if (this.name != "" )
Console.WriteLine("Student's name is {0}", this.name);
else
Console.WriteLine("Student's name is {0}", _name);
}
}
class Teacher
{
private String name;
public Teacher(String _name)
{
this.name = _name;
}
public void getTeacherName(String _name)
{
if (this.name != "")
Console.WriteLine("Teacher's name is {0}", this.name);
else
Console.WriteLine("Teacher's name is {0}", _name);
}
public string getClassName()
{
return "Eanlish";
}
}
}
上述測試代碼運行結(jié)果如下:
當指向簽名不符的方法時會提示如下錯誤,證實了委托的安全性。
下面來看看C#中實現(xiàn)委托有哪些方式及各自主要適用范圍。
1、常規(guī)實現(xiàn)
private delegate String getAString();
static void Main(String []args)
{
int temp = 40;
getAString stringMethod = new getAString(temp.ToString);
Console.WriteLine("String is {0}", stringMethod());//這里stringMethod()等價于調(diào)用temp.ToString();
Console.ReadLine();
}
這段代碼中,實例化了類型為GetAString的一個委托,并對它進行初始化,使它引用整型變量temp的ToString()方法。在C#中,委托在語法上總是接受一個參數(shù)的構(gòu)造函數(shù),這個參數(shù)就是委托引用的方法。上例中stringMethod()等價于使用temp.ToString(),同時也與調(diào)用委托類的Invoke()方法完全相同,實際上,如下圖IL代碼中紅色部分所示,C#編譯器會用stringMethod.Invoke()代替stringMethod()。

為了簡便輸入,C#支持只傳送地址的名稱給委托的實例(委托推斷),如下兩行代碼在編譯器看來是一樣的。
getAString stringMethod = new getAString(temp.ToString);
getAString stringMethod = temp.ToString;
實際上委托的實例可以引用任何類型的任何對象上的實例方法或靜態(tài)方法,只要方法的簽名匹配于委托的簽名即可。所以結(jié)構(gòu)體的方法一樣可以傳遞給委托。
2、多播委托
多播委托具有一個帶有鏈接的委托列表,稱為調(diào)用列表,在對委托實例進行調(diào)用的時候,將按列表中的委托順序進行同步調(diào)用。如果委托有返回值,則將列表中最后一個方法的返回值用作整個委托調(diào)用的返回值。因此,使用多播委托通常具有void返回類型。
可以使用+=來使委托指向多個方法的地址,但必須是在委托實例化之后才可以使用+=來添加新的方法地址(添加重復的方法地址編譯器不會報錯,但是也不會重復執(zhí)行),若想移除其中的方法地址可以使用-=來實現(xiàn)(需要至少保留一個,即對于最后一個方法地址的移除不起作用)。以下代碼中下面兩行無論單獨保留哪行,最終的執(zhí)行結(jié)果都是相同的。
getAString stringMethod = new getAString(temp.ToString);
stringMethod += temp.ToString;
stringMethod -= temp.ToString;
3、委托數(shù)組
delegate double Operations(double x);
class Program
{
static void Main()
{
Operations[] operations =
{
MathOperations.MultiplyByTwo,
MathOperations.Square
};
for (int i = 0; i < operations.Length; i++)
{
Console.WriteLine("Using operations[{0}]:", i);
DisplayNumber(operations[i], 2.0);
DisplayNumber(operations[i], 7.94);
Console.ReadLine();
}
}
static void DisplayNumber(Operations action, double value)
{
double result = action(value);
Console.WriteLine(
"Input Value is {0}, result of operation is {1}", value, result);
}
}
struct MathOperations
{
public static double MultiplyByTwo(double value)
{
return value * 2;
}
public static double Square(double value)
{
return value * value;
}
}
上述代碼中實例化了一個委托數(shù)組operations(與處理類的實例相同),該數(shù)組的元素初始化為MathOperations類的不同操作,遍歷這個數(shù)組,可以將每個操作應用到2個不同的值中。這種用法的好處是,可以在循環(huán)中調(diào)用不同的方法。
相關(guān)文章
C#中將ListView中數(shù)據(jù)導出到Excel的實例方法
首先 你需要添加引用Microsoft Excel 11.0 Object Library2013-04-04C#客戶端程序Visual Studio遠程調(diào)試的方法詳解
這篇文章主要給大家介紹了關(guān)于C#客戶端程序Visual Studio遠程調(diào)試的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-09-09在C#使用字典存儲事件示例及實現(xiàn)自定義事件訪問器
這篇文章主要介紹了在C#使用字典存儲事件示例及實現(xiàn)自定義事件訪問器的方法,是C#事件編程中的基礎(chǔ)知識,需要的朋友可以參考下2016-02-02