C#(un)中的代表解释了示例 - 看起来与方法调用相同

时间:2012-01-20 20:16:38

标签: c# delegates

我终于明白了如何使用委托,但无法弄清楚为什么要使用它们而不是方法调用。我发现这个答案贴在了下面,但我无法弄清楚这两者之间有什么重大区别,因为我可以简单地说

double tot1 = CalcTotalMethod1(100.34);
double tot2 = CalcTotalMethod2(100.34);

而不是

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

这是一个例子:

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

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

4 个答案:

答案 0 :(得分:4)

区别在于您告诉CalcMyTotal使用哪种方法 - 功能组合。 CalcMyTotal不知道所涉及的任何方法(或任何其他你可能想到的方法) - 并且不需要。它需要知道的是“你给我一种做某事的方法,我会做的”。在一个更典型的例子中,CalcMyTotal会做的不仅仅是调用方法,例如:

var somethingTricky = LotsOfWork(amt);
var intermediateValue = calcTotal(somethingTricky);
return SomeMoreWork(intermediateValue);

这里的要点:调用者不需要知道CalcMyTotal内部发生了什么 - 它只需要提供一些“计算总量”的机制; CalcMyTotal并不需要了解所涉及的机制。您可以将其视为单方法接口。

为了完整起见,你也可以这样做(也许更清楚):

public static double CalcMyTotal(double amt, Func<double,double> calcTotal) {...}

(注意Func<...>用法),并使用lambda语法调用:

double tot1 = CalcMyTotal(100.34, amt => amt * 0.014);

答案 1 :(得分:4)

因为你正在处理琐碎的例子......

想象一下,如果您是图书馆的设计者,您希望其他人将不同的方法传递给CalcMyTotal。

或.....也许更简单,当有人点击用户界面上的按钮时,您希望能够在单击按钮时插入不同的功能以执行不同的操作

答案 2 :(得分:3)

有些不同之处:

  • 委托允许multicasting(即,其调用列表中的委托类型的多个元素)。
  • 委托允许在调用者和被调用的特定函数之间进行某种程度的解耦。
  • 以上内容允许将代理发送到对订阅者和实现一无所知的函数中。然后,您有发布者/订阅者模式的实现。
  • 代表是创建事件的垫脚石,它使用代理向0-N订阅者通知特定事件已发生的事实,并向所有订阅者传递描述事件详细信息的数据。

答案 3 :(得分:2)

当您需要传递对方法的引用时,委托最有用。示例包括events in C#sorting with a custom comparator

后者的一个例子:

class Thing
{
    private int value;

    public static int CompareTwoThings(Thing one, Thing other)
    {
        if (one.value < other.value) return -1;
        if (one.value > other.value) return 1;
        return 0;
    }
}

// elsewhere
List<Thing> things = GetSomeThings();
things.Sort(Thing.CompareTwoThings);

当然,在这种情况下,您确实应该Thing实现IComparable,但这只是一个如何将委托用作自定义排序函数的示例。