欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c#委托詳解和和示例分享

 更新時(shí)間:2014年03月23日 12:09:49   作者:  
這篇文章詳細(xì)探討了C#中的委托,列舉其主要的實(shí)現(xiàn)方式,并分析其在設(shè)計(jì)層面和編碼層面帶來的好處,最后會(huì)討論其安全性和執(zhí)行效率等,當(dāng)然還有實(shí)現(xiàn)示例
什么是委托?

委托是尋址方法的.NET版本,使用委托可以將方法作為參數(shù)進(jìn)行傳遞。委托是一種特殊類型的對(duì)象,其特殊之處在于委托中包含的只是一個(gè)活多個(gè)方法的地址,而不是數(shù)據(jù)。

委托雖然看起來像是一種類型,但其實(shí)定義一個(gè)委托,是定義了一個(gè)新的類。下面這行代碼,定義了一個(gè)委托,使用ILDasm.exe查看其生成的IL代碼如圖所示:

復(fù)制代碼 代碼如下:

//定義委托,它定義了可以代表的方法的類型,但其本身卻是一個(gè)類
 public delegate int methodDelegate(string str);

032101

由圖中紅色框線中可以看出,.NET將委托定義為一個(gè)密封類,派生自基類System.MulticastDelegate,并繼承了基類的三個(gè)方法(稍后討論這三個(gè))。

委托與函數(shù)指針的區(qū)別

1、安全性:C/C++的函數(shù)指針只是提取了函數(shù)的地址,并作為一個(gè)參數(shù)傳遞它,沒有類型安全性,可以把任何函數(shù)傳遞給需要函數(shù)指針的地方;而.NET中的委托是類型安全的。

2、與實(shí)例的關(guān)聯(lián)性:在面向?qū)ο缶幊讨?,幾乎沒有方法是孤立存在的,而是在調(diào)用方法前通常需要與類實(shí)例相關(guān)聯(lián)。委托可以獲取到類實(shí)例中的信息,從而實(shí)現(xiàn)與實(shí)例的關(guān)聯(lián)。

3、本質(zhì)上函數(shù)指針是一個(gè)指針變量,分配在棧中;委托類型聲明的是一個(gè)類,實(shí)例化為一個(gè)對(duì)象,分配在堆中。

4、委托可以指向不同類中具有相同參數(shù)和簽名的函數(shù),函數(shù)指針則不可以。

復(fù)制代碼 代碼如下:

namespace ConsoleApplication1
{
    //定義委托,它定義了可以代表的方法的類型,但其本身卻是一個(gè)類
    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; 指向簽名不符的方法時(shí)提示錯(cuò)誤!
            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";
        }
    }
}

上述測(cè)試代碼運(yùn)行結(jié)果如下:

當(dāng)指向簽名不符的方法時(shí)會(huì)提示如下錯(cuò)誤,證實(shí)了委托的安全性。

下面來看看C#中實(shí)現(xiàn)委托有哪些方式及各自主要適用范圍。

1、常規(guī)實(shí)現(xiàn)

復(fù)制代碼 代碼如下:

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()等價(jià)于調(diào)用temp.ToString();
    Console.ReadLine();
}


這段代碼中,實(shí)例化了類型為GetAString的一個(gè)委托,并對(duì)它進(jìn)行初始化,使它引用整型變量temp的ToString()方法。在C#中,委托在語法上總是接受一個(gè)參數(shù)的構(gòu)造函數(shù),這個(gè)參數(shù)就是委托引用的方法。上例中stringMethod()等價(jià)于使用temp.ToString(),同時(shí)也與調(diào)用委托類的Invoke()方法完全相同,實(shí)際上,如下圖IL代碼中紅色部分所示,C#編譯器會(huì)用stringMethod.Invoke()代替stringMethod()。

為了簡(jiǎn)便輸入,C#支持只傳送地址的名稱給委托的實(shí)例(委托推斷),如下兩行代碼在編譯器看來是一樣的。

復(fù)制代碼 代碼如下:

getAString stringMethod = new getAString(temp.ToString);
getAString stringMethod = temp.ToString;

實(shí)際上委托的實(shí)例可以引用任何類型的任何對(duì)象上的實(shí)例方法或靜態(tài)方法,只要方法的簽名匹配于委托的簽名即可。所以結(jié)構(gòu)體的方法一樣可以傳遞給委托。

2、多播委托
多播委托具有一個(gè)帶有鏈接的委托列表,稱為調(diào)用列表,在對(duì)委托實(shí)例進(jìn)行調(diào)用的時(shí)候,將按列表中的委托順序進(jìn)行同步調(diào)用。如果委托有返回值,則將列表中最后一個(gè)方法的返回值用作整個(gè)委托調(diào)用的返回值。因此,使用多播委托通常具有void返回類型。

可以使用+=來使委托指向多個(gè)方法的地址,但必須是在委托實(shí)例化之后才可以使用+=來添加新的方法地址(添加重復(fù)的方法地址編譯器不會(huì)報(bào)錯(cuò),但是也不會(huì)重復(fù)執(zhí)行),若想移除其中的方法地址可以使用-=來實(shí)現(xiàn)(需要至少保留一個(gè),即對(duì)于最后一個(gè)方法地址的移除不起作用)。以下代碼中下面兩行無論單獨(dú)保留哪行,最終的執(zhí)行結(jié)果都是相同的。

復(fù)制代碼 代碼如下:

getAString stringMethod = new getAString(temp.ToString);
stringMethod += temp.ToString;
stringMethod -= temp.ToString;
 

3、委托數(shù)組

復(fù)制代碼 代碼如下:

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í)例化了一個(gè)委托數(shù)組operations(與處理類的實(shí)例相同),該數(shù)組的元素初始化為MathOperations類的不同操作,遍歷這個(gè)數(shù)組,可以將每個(gè)操作應(yīng)用到2個(gè)不同的值中。這種用法的好處是,可以在循環(huán)中調(diào)用不同的方法。

相關(guān)文章

最新評(píng)論