代表们,为什么?

Mag*_*age 55 c# delegates

可能重复:
您何时在C#中使用委托?
代表们的目的

我看到很多关于代表使用的问题.我仍然不清楚你在哪里和为什么使用代理而不是直接调用方法.

我多次听过这个短语:"然后可以将委托对象传递给可以调用引用方法的代码,而不必在编译时知道将调用哪个方法."

我不明白这句话是怎么回事.

我写了以下例子.假设您有3个具有相同参数的方法:

   public int add(int x, int y)
    {
        int total;
        return total = x + y;
    }
    public int multiply(int x, int y)
    {
        int total;
        return total = x * y;
    }
    public int subtract(int x, int y)
    {
        int total;
        return total = x - y;
    }
Run Code Online (Sandbox Code Playgroud)

现在我宣布一个代表:

public delegate int Operations(int x, int y);
Run Code Online (Sandbox Code Playgroud)

现在我可以更进一步声明一个处理程序来使用这个委托(或你的委托直接)

致电代表:

MyClass f = new MyClass();

Operations p = new Operations(f.multiply);
p.Invoke(5, 5);
Run Code Online (Sandbox Code Playgroud)

或者使用处理程序调用

f.OperationsHandler = f.multiply;
//just displaying result to text as an example
textBoxDelegate.Text = f.OperationsHandler.Invoke(5, 5).ToString();
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,我都看到了我的"乘法"方法.为什么人们使用"在运行时更改功能"或上面的短语?

为什么每次我声明一个委托时都会使用委托,它需要一个指向的方法?如果它需要一个指向的方法,为什么不直接调用该方法?在我看来,我必须编写更多的代码来使用委托,而不仅仅是直接使用这些函数.

有人可以请给我一个真实世界的情况吗?我完全糊涂了.

Dan*_*Tao 28

在运行时更改功能不是代理人完成的任务.

基本上,代表可以为您节省大量的打字工作.

例如:

class Person
{
    public string Name { get; }
    public int Age { get; }
    public double Height { get; }
    public double Weight { get; }
}

IEnumerable<Person> people = GetPeople();

var orderedByName = people.OrderBy(p => p.Name);
var orderedByAge = people.OrderBy(p => p.Age);
var orderedByHeight = people.OrderBy(p => p.Height);
var orderedByWeight = people.OrderBy(p => p.Weight);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,p => p.Name,p => p.Age等是评估所有lambda表达式Func<Person, T>代表(其中Tstring,int,double,和double,分别地).

现在让我们考虑如何在没有代表的情况下实现上述目标.我们不必让OrderBy方法采用委托参数,而是放弃通用性并定义这些方法:

public static IEnumerable<Person> OrderByName(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByAge(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByHeight(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByWeight(this IEnumerable<Person> people);
Run Code Online (Sandbox Code Playgroud)

完全是糟透了.我的意思是,首先,代码变得无限可重用,因为它只适用于该Person类型的集合.此外,我们需要复制和粘贴相同的代码四次,每个副本中只更改1或2行(Person引用相关属性- 否则它们看起来都一样)!这很快就会变得难以维持.

因此,委托允许您通过抽象出可以切入和切出的代码中的某些行为,使您的代码更具可重用性更易维护性.


Cra*_*ney 12

代表非常有用,特别是在引入linq和闭包之后.

一个很好的例子是'Where'函数,它是标准linq方法之一.'where'采用列表和过滤器,并返回与过滤器匹配的项目列表.(filter参数是一个委托,它接受一个T并返回一个布尔值.)

因为它使用委托来指定过滤器,所以Where函数非常灵活.例如,您不需要使用不同的Where函数来过滤奇数和素数.调用语法也非常简洁,如果使用接口或抽象类则不会出现这种情况.

更具体地说,服用代表的意思是你可以这样写:

var result = list.Where(x => x != null);
...
Run Code Online (Sandbox Code Playgroud)

而不是这个:

var result = new List<T>();
foreach (var e in list)
    if (e != null)
        result.add(e)
...
Run Code Online (Sandbox Code Playgroud)


Jef*_*nal 9

为什么每次我声明一个委托时都会使用委托,它需要一个指向的方法?如果它需要一个指向的方法,为什么不直接调用该方法?

与接口类似,委托允许您对代码进行分离和概括.您通常使用委托时,你不提前哪些方法你会想知道执行-当你只知道你要执行的东西符合一定的签名.

例如,考虑一个定期执行某些方法的计时器类:

public delegate void SimpleAction();

public class Timer {
    public Timer(int secondsBetweenActions, SimpleAction simpleAction) {}
}
Run Code Online (Sandbox Code Playgroud)

您可以将任何东西到该定时器,这样你就可以在任何其他项目或应用程序中使用,但不尝试预测你将如何使用它,并没有限制其使用的是你在想的情景极少数现在.


Ste*_*dit 7

让我举个例子.如果你的类暴露了一个event,它可以在运行时被分配一些代理,这将被调用以表示发生了什么.当你写这个课时,你不知道代表什么会结束.相反,这取决于谁使用你的班级.