什么是代表?[关闭]


152

我很困惑代表的实际角色是什么?

我在面试中多次被问到这个问题,但我认为面试官对我的回答不满意。

有人可以用一个实例告诉我最好的定义吗?


21
出于好奇,您对此有何反应,以便我们告诉您如何解决?
Anthony Forloney,2010年

6
我觉得很有趣,这个问题已经关闭,但有126个投票和65个人将其标记为收藏。看起来,即使范围太广,这仍然是一个很好的问题。
Rich

Answers:


171

我喜欢将委托视为“指向函数的指针”。这可以追溯到C天,但是这个想法仍然成立。

这个想法是,您需要能够调用一段代码,但是要在运行时才知道要调用的那段代码。因此,您可以为此目的使用“代表”。委托对于事件处理程序之类的事情派上用场,例如,您可以根据不同的事件来执行不同的事情。

这是您可以查看的C#参考:

例如,在C#中,我们有一个想要进行的计算,并且想使用一种直到运行时才知道的不同的计算方法。因此,我们可能有两种类似的计算方法:

public static double CalcTotalMethod1(double amt)
{
    return amt * .014;
}

public static double CalcTotalMethod2(double amt)
{
    return amt * .056 + 42.43;
}

我们可以这样声明一个委托签名:

public delegate double calcTotalDelegate(double amt);

然后我们可以声明一个将委托作为参数的方法,如下所示:

public static double CalcMyTotal(double amt, calcTotalDelegate calcTotal)
{
    return calcTotal(amt);
}

我们可以调用该CalcMyTotal方法,以传入我们要使用的委托方法。

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);

19
+1的点头C中的简单而有效的函数指针
艾登贝尔

3
一个问题与您的答案有关。与以常规方式调用函数有什么真正的不同?正因为如此,它在运行时未知?
函数naveed

1
@NAVEED-参考我的最新编辑,我提供了一个示例。就实际的方法调用而言,它与上面的示例中的普通方法调用没有什么不同(calcTotal(amt)正在调用委托),但是委托的功能在于您可以将它们用作参数,等等,当您希望某个方法能够具有不同的行为时。您还可以使用许多其他功能,这只是一个简单的示例。希望有帮助。
dcp 2010年

它在运行时未知,它是一个绑定函数,而不是一个自由函数- Foo向委托分配一个非静态方法将调用this.Foo()而不是像函数指针那样执行一个静态函数(在C中,您通常有一个额外的void*参数传递this给函数指针)
Pete Kirkham 2010年

1
+1是快速有效的示例,用于建立与C / C ++中的函数指针的相似性。非常感激!
2013年

19

委托只是一个函数指针。
只需为您分配希望运行委托的方法即可。然后在代码中稍后可以通过Invoke调用该方法。

一些代码演示(从内存中写出来,因此语法可能关闭)

delegate void delMyDelegate(object o);

private void MethodToExecute1(object o)
{
    // do something with object
}

private void MethodToExecute2(object o)
{
    // do something else with object
}

private void DoSomethingToList(delMyDelegate methodToRun)
{
    foreach(object o in myList)
        methodToRun.Invoke(o);
}

public void ApplyMethodsToList()
{
    DoSomethingToList(MethodToExecute1);
    DoSomethingToList(MethodToExecute2);
}

16

从这里取

什么是代表?
答:当一个对象接收到一个请求时,该对象可以自己处理请求,也可以将请求传递给第二个对象来完成工作。如果对象决定继续传递请求,则表示该对象已将处理请求的责任转发给第二个对象。

或者,举一个简单的伪示例:某事物向object1发送了一个请求。然后object1将请求及其本身转发到object2-委托。object2处理请求并完成一些工作。(注意:上面的链接给出了很好的例子)


上面链接中给出的示例未正确说明委派。
Hardik9850


4

委托是可以引用方法的对象。因此,当我们创建委托时,我们正在创建一个对象,该对象可以保存对方法的引用。此外,可以通过该引用调用该方法。因此,委托可以调用其引用的方法。委托的主要优点是它允许我们指定对方法的调用,但是实际调用的方法是在运行时而不是在编译时确定的。

简单代表

Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)

http://knowpacific.wordpress.com/2012/01/26/delegate/


2

在这里,我将解释委托,多播委托及其用法。委托是一种在对象中保存方法引用的类型。它也称为类型安全功能指针。我们可以说委托是一种定义方法签名的类型。

实例化委托时,可以将其实例与具有兼容签名的任何方法相关联。您可以通过委托实例调用(或调用)方法。委托用于将方法作为参数传递给其他方法。事件处理程序不过是通过委托调用的方法。使用委托的好处是,封装了调用方的方法调用。有效使用委托可以提高应用程序的性能。用来异步调用方法。有一些代表的属性是

Delegates are like C++ function pointers but are type safe.
Delegates allow methods to be passed as parameters.
Delegates can be used to define callback methods.
Delegates can be chained together; for example, multiple methods can be called on a single event.
Methods do not have to match the delegate signature exactly.

公共代理人type_of_delegate委托人名称()//声明

You can use delegates without parameters or with parameter list
If you are referring to the method with some data type then the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer. Here I am giving an example with String.

以下示例显示了委托操作:

    namespace MyDelegate
    {
        class Program
        {
            private delegate void Show(string s);


            // Create a method for a delegate.
            public static void MyDelegateMethod(string me

ssage)
        {
            System.Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            Show p = MyDelegateMethod;
            p("My Delegate");
            p.Invoke("My Delegate");
            System.Console.ReadLine();
        }
    }
}

什么是多播代表?

它是一个委托,拥有多个方法的引用。多播委托必须仅包含返回void的方法,否则将存在运行时异常。

 delegate void MyMulticastDelegate(int i, string s);
 Class Class2
 {
  static void MyFirstDelegateMethod(int i, string s)
  {
    Console.WriteLine("My First Method");
  }

  static void MySecondDelegateMethod(int i, string s)
  {
    Console.WriteLine("My Second Method");
  }

  static void Main(string[] args)
  {
    MyMulticastDelegate Method= new MyMulticastDelegate(MyFirstDelegateMethod);
    Method+= new MyMulticastDelegate (MySecondDelegateMethod);
    Method(1,"Hi");             // Calling 2 Methodscalled
    Method-= new MyMulticastDelegate (MyFirstDelegateMethod);
    Method(2,"Hi");             //Only 2nd Method calling
  }
}

在这里,使用+ =运算符添加代表,使用-=运算符删除代表。

委托类型派生自.NET Framework中的Delegate类。委托类型是密封的-无法派生。由于实例化的委托是一个对象,因此可以将其作为参数传递或分配给属性。这允许方法接受委托作为参数,并在以后的某个时间调用委托。这称为异步回调。


1

在Google收藏集转发类(也称为Decorator模式)中可以找到有关Delegate模式的很好的解释和实际实现。


1

在事件通信中,发送者不知道哪个对象将处理事件。委托是保存方法引用的类型。委托具有签名,并持有与其签名匹配的方法的引用,因此委托类似于类型安全函数指针。

button1.Click + = new System.EventHandler(button1_Click)System.EventHandler在这里被声明为委托。

当您不知道在运行时要调用哪些代码时,可以使用委托,因此,那时使用委托来处理事件

http://msdn.microsoft.com/zh-CN/library/ms173171(v=vs.80).aspx


1

一个委托对象 是一个对象,当事情在发生对象另一个对象协商。例如,如果您的汽车发生故障,您的维修人员就是您的代表。您去找维修人员,请他为您修理汽车(尽管有些人更愿意自己修理汽车,在这种情况下,他们是他们自己的汽车维修代表)。


1

委托是代表函数指针的对象。但是,它不是普通的函数指针,因为它:

1)是面向对象的

2)类型安全,即它只能指向一个方法,而您不能读取它指向的原始内存地址

3)是强类型的。它只能指向与其签名匹配的方法。

4)可以同时指向多个方法。


1

代表主要用于事件。

需要是:

您不希望在运行程序时执行任何代码。运行该程序后,您希望每当事件发生时执行该代码段。

范例:

  1. 控制台应用程序 -代码只能在运行程序时执行。(写在Main方法里面)
  2. Windows应用程序(用户界面编程)-运行程序后单击按钮即可执行代码。

他们就是这么说的,您不知道在编译时将调用哪种方法。您仅在单击按钮时才在运行时知道它。

没有委托,就不可能进行用户界面编程。因为每当用户发生以下事件时,您都在执行代码:单击button,在文本框中键入内容,选择dropdownlist项目等等。


0

委托是将任务委托到的东西。委托的主要目的是使代码解耦,并允许更大的灵活性和重用性。

在编程中,尤其是在面向对象的编程中,这意味着调用一个方法来执行某些工作时,它将把工作传递给它具有引用的另一个对象的方法。只要对象符合一组预定义的方法,该引用就可以指向我们想要的任何对象。我们称其为“接口编程”(相对于具体类实现的编程)。接口基本上是通用模板,没有任何实现。它仅表示一个配方,一组方法,先决条件和后置条件(规则)。

简单的例子:

SomeInterface
{
   public void doSomething();
}


SomeImplementation implements SomeInterface
{
   public void doSomething()
   {
      System.err.println("Was it good for you?");
   }

}


SomeCaller
{
   public void doIt(SomeInterface someInterface)
   {
      someInterface.doSomething();
   }
}

现在您看到我可以随时使用所需的任何实现,而无需更改SomeCaller中的代码,因为doIt()传递的类型不是具体的而是抽象的,因为它是接口。在Java世界中,这通常表现在服务范式中,在该范式中,您调出服务(通过特定接口将其本身宣传为服务的对象),然后该服务调出给委托人以帮助其完成工作。该服务的方法被命名为粗粒度任务(makePayment(),createNewUser()等),而在内部,如果通过委派完成了很多工作,它会做很多事情,委托的类型是接口而不是具体的实现。

SomeService
{
    SomeInterface someImplementation = ... // assign here
    SomeOtherInterface someOtherImplementation = ... // okay, let's add a second

    public void doSomeWork()
    {
         someImplementation.doSomething();
         someOtherImplementation.doSomethingElse();
    }
}

(注意:如何分配实现不在此线程的讨论范围之内。控制和依赖注入的查找反转。)


-2

虽然不是真正的“函数指针”,但委托可能看起来像是一种动态语言,如PHP:



$func = 'foo';
$func();

function foo() {
    print 'foo';
}

或使用JavaScript,您可以执行以下操作:


var func = function(){ alert('foo!'); }
func();


2
这不是委派的示例。在您的示例中,您使用的是所谓的变量函数,它基本上是在寻找与变量所引用的字符串具有相同名称的函数。参见变量函数:php.net/manual/en/functions.variable-functions.php
Aquarelle
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.