2010-09-20 42 views
7

我明白委托封装方法调用。不过,我很难理解他们的需求。为什么要使用代表,他们设计了什么样的情况?与代表达成什么协议?

+7

每当我读到这个问题,我听到它的杰里宋飞的声音的称号。 – Jess 2010-09-20 13:49:52

回答

11

委托本质上是一个方法指针。委托让我们创建一个引用变量,但不是引用一个类的实例,而是引用类中的方法。它引用具有返回类型并具有与该委托指定的相同参数的任何方法。这是一个非常有用的事件。为了彻底阅读,我建议您阅读Head First C#(Andrew Stellman和Jennifer Greene撰写)中的主题。它精美地解释了委托主题以及.NET中的大多数概念。

+0

真棒描述.. – 2010-09-21 14:25:03

4

代表经常用于Events。根据MSDN,在.NET委托设计用于以下情况:使用

  • 的三项赛的设计模式。
  • 需要封装一个静态方法。
  • 调用者无需访问实现该方法的对象上的其他属性,方法或接口。
  • 简单的组成是期望的。
  • 一个类可能需要一个以上的实施方法

从MSDN另一公把解释的methodimplementation的,

一个使用 单方法接口而不是很好的例子代表 的代表是IComparableIComparableIComparable声明 CompareTo方法,该方法返回一个指定小于,等于 到的 整数,或者返回相同类型的两个对象之间的关系 。 IComparable可以用作排序算法的基础 ,而使用 代表比较方法作为排序算法的基础 将是 有效,这是不理想的。由于 比较的能力属于 类,并且比较算法 在运行时不会更改,因此单方法接口是ideal.single-method接口是理想的。

由于.NET 2.0它也被用于anonymous functions

维基百科有关于委托模式一个很好的解释,

在软件工程中,委托模式是在面向对象的程序设计模式,其中一个对象,而不是执行其既定任务之一,代表该任务发送给关联的助手对象。它通过了负面影响,可以这么说(技术上来说,是一种责任倒置)。辅助对象称为委托。委托模式是构成其他软件模式(如组合(也称为聚合),混合和方面)的基本抽象模式之一。

8

好,一些常见的用途:

  • 事件处理程序(在UI代码很常见的 - “当单击该按钮时,我想这个代码执行”)从异步调用
  • 回调
  • 提供的螺纹(或线程池)用新的任务来执行
  • 指定LINQ突起/条件等

不要认为它们是封装方法调用。把它们想象成封装一些具有特定签名的任意行为/逻辑。 “方法”部分有些不相关。

另一种思考委托类型的方法是作为单一方法的接口。一个很好的例子就是IComparer<T>接口及其双重代理类型Comparison<T>。他们代表了相同的基本想法;有时候更容易将其表示为委托,而其他时候界面使生活更轻松。 (当然,您可以轻松地编写代码来在两者之间进行转换。)

0

代表允许您传递对方法的引用。一个常见的例子是将比较方法传递给排序函数。

5

它们的设计意义非常广泛,因为当你知道需要调用其他代码的代码时 - 但在编译时你不知道其他代码可能是什么。

作为示例,请考虑使用委托的Windows窗体Button.Click事件。 Windows窗体程序员知道,当按下按钮时,你会想要发生某种事情,但他们无法确切知道你想要做什么......它可能是任何东西!

因此,您创建一个方法并将其分配给一个委托并将其设置为该事件,并且在那里。这是代表们的基本推理,尽管他们有很多其他相关的好用途。

0

如果您需要在运行时决定调用哪种方法,那么您使用委托。然后代理将在运行时响应某些动作/事件,并调用适当的方法。这就像发送一个“代表”到你不想参加的婚礼:-)

C人会认识到这是一个函数指针,但不要被这里的术语所困扰。所有委托人(并且实际上是一种类型)都提供了方法的签名,稍后将调用该方法来实现适当的逻辑。

的“画报C#”一书由丹·索利斯提供了学习这个概念的最简单的切入点,我所遇到的:

http://www.amazon.com/Illustrated-2008-Windows-Net-Daniel-Solis/dp/1590599543

+0

虽然我碰巧很喜欢A按...有什么用链接一个“尚未公布”的书? – WernerCD 2010-09-20 13:48:35

+0

@WernerCD,感谢您的单挑。有两个以前的版本,所以更新链接:-) – IrishChieftain 2010-09-20 13:50:46

+0

我绝对爱C#图解2008年,恰好等待2010年发布......这是我第一次注意到嘿:) – WernerCD 2010-09-20 14:13:57

0

委托是典型的对象引用和指针的组合到对象的类方法之一(可以为静态方法创建委托,在这种情况下,没有对象引用)。可以调用委托而不考虑包含对象的类型,因为包含的方法指针保证对包含的对象有效。

为了理解代表背后的一些用处,回想一下C语言和函数的printf“家族”。假设你想拥有一个通用版本的“printf”,它不仅可以是用作printf,fprintf,sprintf等,但可以将其输出发送到串行端口,文本框,TCP端口,cookie结霜机器或其他任何设备,而无需预先分配缓冲区。显然,这样的函数需要接受字符输出例程的函数指针,但这本身通常是不够的。

一个典型的实现(不幸的是不标准化)将有一个通用的gp_printf例程,它接受(除了格式字符串和输出参数)void指针和指向一个函数的指针,该函数接受一个字符和一个void指针。 gp_printf例程本身不会使用传入的void指针,但会将它传递给字符输出函数。然后,该函数可以将指针转换为FILE *(如果gprint_printf被fprintf调用)或char **(如果它被sprintf调用)或SERIAL_PORT *(如果它被serial_printf调用),或者。

请注意,因为任何类型的信息都可以通过void *传递,所以gp_printf可以做什么没有限制。但是,如果在void *中传递的信息不是函数期望的信息,那么可能会导致未定义的行为(即可能非常糟糕的事情)。调用者的责任是确保函数指针和void *正确配对;系统中没有任何东西可以防止不正确的使用。

在.net中,委托可以提供函数指针和void *上面的组合功能,还有额外的好处是委托的构造函数可以确保数据是函数的正确类型。一个方便的功能。

1

过度简化:我会说,委托是一个函数的占位符,直到某些事情将某个实际功能分配给该委托时为止。调用未分配的委托会引发异常。

混乱发生是因为定义,声明,实例化和委托调用之间通常没有什么区别。

定义:
在命名空间将这个就像任何类定义。

public delegate bool DoSomething(string withThis); 

这相当于类定义,因为您现在可以声明此代理的变量。

声明:
把这是一个函数例程,就像你会声明任何变量。

DoSomething doSth; 

实例化和分配:
通常你会连同申报做到这一点。

doSth = new DoSomething(MyDoSomethingFunc); 

“新的DoSomething(..)”是实例。 doSth = ...是任务。

请注意,您必须已经定义了一个名为“MyDoSomething”功能,将一个字符串返回一个布尔值。

然后,你可以调用函数。

调用:

bool result = doSth(myStringValue); 

活动:
你可以看到事件进来:

由于类的成员通常是基于定义的声明。

class MyClass { 
    private int MyMember; 
} 

事件是基于委托声明:

public delegate bool DoSomething(string withWhat); 

class MyClass { 
    private event DoSomething MyEvent; 
} 

与前面的例子不同的是,事件是“特殊”:

  1. 您可以致电未分配的事件而不引发异常。
  2. 可以将多个功能的事件。然后他们将依次被调用。如果其中一个调用引发异常,其他调用将无法播放。

他们真的是代表阵列的语法糖。

的一点是当然的东西/别人会做分配给你的。