当前位置:  编程技术>.net/c#/asp.net

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

    来源: 互联网  发布时间:2014-10-29

    本文导语:  什么是委托? 委托是寻址方法的.NET版本,使用委托可以将方法作为参数进行传递。委托是一种特殊类型的对象,其特殊之处在于委托中包含的只是一个活多个方法的地址,而不是数据。 委托虽然看起来像是一种类型,但其...

什么是委托?

委托是寻址方法的.NET版本,使用委托可以将方法作为参数进行传递。委托是一种特殊类型的对象,其特殊之处在于委托中包含的只是一个活多个方法的地址,而不是数据。

委托虽然看起来像是一种类型,但其实定义一个委托,是定义了一个新的类。下面这行代码,定义了一个委托,使用ILDasm.exe查看其生成的IL代码如图所示:

代码如下:

//定义委托,它定义了可以代表的方法的类型,但其本身却是一个类
 public delegate int methodDelegate(string str);

由图中红色框线中可以看出,.NET将委托定义为一个密封类,派生自基类System.MulticastDelegate,并继承了基类的三个方法(稍后讨论这三个)。

委托与函数指针的区别

1、安全性:C/C++的函数指针只是提取了函数的地址,并作为一个参数传递它,没有类型安全性,可以把任何函数传递给需要函数指针的地方;而.NET中的委托是类型安全的。

2、与实例的关联性:在面向对象编程中,几乎没有方法是孤立存在的,而是在调用方法前通常需要与类实例相关联。委托可以获取到类实例中的信息,从而实现与实例的关联。

3、本质上函数指针是一个指针变量,分配在栈中;委托类型声明的是一个类,实例化为一个对象,分配在堆中。

4、委托可以指向不同类中具有相同参数和签名的函数,函数指针则不可以。

代码如下:

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";
        }
    }
}

上述测试代码运行结果如下:

当指向签名不符的方法时会提示如下错误,证实了委托的安全性。

下面来看看C#中实现委托有哪些方式及各自主要适用范围。

1、常规实现

代码如下:

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()等价于调用temp.ToString();
    Console.ReadLine();
}


这段代码中,实例化了类型为GetAString的一个委托,并对它进行初始化,使它引用整型变量temp的ToString()方法。在C#中,委托在语法上总是接受一个参数的构造函数,这个参数就是委托引用的方法。上例中stringMethod()等价于使用temp.ToString(),同时也与调用委托类的Invoke()方法完全相同,实际上,如下图IL代码中红色部分所示,C#编译器会用stringMethod.Invoke()代替stringMethod()。

为了简便输入,C#支持只传送地址的名称给委托的实例(委托推断),如下两行代码在编译器看来是一样的。

代码如下:

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

实际上委托的实例可以引用任何类型的任何对象上的实例方法或静态方法,只要方法的签名匹配于委托的签名即可。所以结构体的方法一样可以传递给委托。

2、多播委托
多播委托具有一个带有链接的委托列表,称为调用列表,在对委托实例进行调用的时候,将按列表中的委托顺序进行同步调用。如果委托有返回值,则将列表中最后一个方法的返回值用作整个委托调用的返回值。因此,使用多播委托通常具有void返回类型。

可以使用+=来使委托指向多个方法的地址,但必须是在委托实例化之后才可以使用+=来添加新的方法地址(添加重复的方法地址编译器不会报错,但是也不会重复执行),若想移除其中的方法地址可以使用-=来实现(需要至少保留一个,即对于最后一个方法地址的移除不起作用)。以下代码中下面两行无论单独保留哪行,最终的执行结果都是相同的。

代码如下:

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

3、委托数组

代码如下:

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;
}
    }

上述代码中实例化了一个委托数组operations(与处理类的实例相同),该数组的元素初始化为MathOperations类的不同操作,遍历这个数组,可以将每个操作应用到2个不同的值中。这种用法的好处是,可以在循环中调用不同的方法。


    
 
 

您可能感兴趣的文章:

  • c#通过委托delegate与Dictionary实现action选择器代码举例
  • c#委托与多播委托的实例代码
  • C# 委托(delegate) 的小例子
  • C#实现的几种委托方式介绍
  • C#事件处理和委托event delegate实例简述
  • C#学习笔记之多播委托的例子
  • c# 委托浅析
  • C#委托初级使用的实例代码
  • C#委托delegate实例解析
  • C# 中如何利用lambda实现委托事件的挂接
  • C#基础之泛型委托实例教程
  • 深入c# Func委托的详解
  • C#委托所蕴含的函数指针概念详细解析
  • C#基础之委托用法实例教程
  • C#用Lambda和委托实现模板方法
  • c#委托把方法当成参数(实例讲解)
  • C#匿名委托和Java匿名局部内部类使用方法示例
  • c# 委托与事件的小例子
  • c# 委托和事件实例学习
  • C#入门学习笔记之事件和委托的实例
  • C# 委托(跨窗体操作控件)实例流程讲解
  • c#委托学习示例分享
  • C# 委托的三种调用示例(同步调用 异步调用 异步回调)
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 深入委托与多播委托的详解
  • C#中常见的系统内置委托用法详解
  • 使用BeginInvoke,EndInvoke异步调用委托的代码
  • 基于使用BeginInvoke,EndInvoke异步调用委托的实现代码
  • winform使用委托和事件来完成两个窗体之间通信的实例
  • 探讨:如何使用委托,匿名方法对集合进行万能排序
  • 经典的委托排序(深入分析)
  • C#零基础学习理解委托
  • 探讨如何用委托处理排序
  • c# 委托反射 DataTable转换为实体集的方法
  • c#使用委托反射将DataTable转换为实体集的代码
  • c#中利用委托反射将DataTable转换为实体集的代码
  • 学习 asp.net 的事件与委托
  • C#泛型:泛型特点、泛型继承、泛型接口、泛型委托学习笔记
  • c#并行任务多种优化方案分享(异步委托)
  • 深入理解C#中常见的委托


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3