简体   繁体   English

.NET中委托的目的是什么?

[英]What is the purpose of delegates in .NET

So I'm a little bit confused about delegates in C#.... what do they do and how are they useful? 所以我对C#中的代表感到有点困惑....他们做了什么以及它们如何有用? I've read a few tutorials, and I don't really get exactly what they're supposed to do (everyone relates them to function pointers in C, and I've never programmed in C). 我已经阅读了一些教程,我并没有真正得到它们应该做的事情(每个人都将它们与C中的函数指针联系起来,而我从未在C中编程)。

So... what do delegates do? 所以...代表们做了什么? What's a scenario in which I should use them? 我应该使用它们的场景是什么? How would I then use them? 那我怎么用呢?

The other answers are good, but here's another way to think about delegates that might help. 其他答案都很好,但这是考虑可能有所帮助的代表的另一种方式。 Imagine that a delegate is nothing more than an interface. 想象一下,委托只不过是一个界面。 When you see: 当你看到:

delegate void Action();

think: 认为:

interface IAction
{
    void Invoke();
}

And when you see: 当你看到:

Action myAction = foo.Bar;

think: 认为:

class FooBarAction : IAction
{
    public Foo Receiver { get; private set; }
    public FooBarAction(Foo foo)
    {
        this.Receiver = foo;
    }
    public void Invoke()
    {
        this.Receiver.Bar();
    }
}
...
IAction myAction = new FooBarAction(foo);

And when you see 当你看到

myAction();

think 认为

myAction.Invoke();

The actual details of what types get constructed are a bit different, but fundamentally that's what's happening. 构建什么类型的实际细节有点不同,但从根本上说这就是正在发生的事情。 A delegate is simply an object with a method called Invoke, and when you call that method, it calls some other method on some other object on your behalf . 委托只是一个名为Invoke的方法的对象,当您调用该方法时,它代表您在其他对象调用其他方法。 That's why it's called a "delegate" -- because it delegates the call to another method of another object. 这就是为什么它被称为“委托” - 因为它将调用委托给另一个对象的另一个方法。

Delegates are sort of like objects that represent a method call. 委托类似于表示方法调用的对象。 One useful way they can be used are as callbacks. 可以使用它们的一种有用方法是作为回调。 For example, imagine you have a method that does something asynchronous, and you want the caller to be able to specify what they want to happen once it completes ( Action is a type of delegate): 例如,假设您有一个执行异步操作的方法,并且您希望调用者能够在完成后指定他们想要发生的事情( Action是一种委托):

public void DoSomething(Action whatToDoWhenDone)
{
    // Your code

    // See how the delegate is called like a method
    whatToDoWhenDone();
}

A user of DoSomething can now specify the callback as a parameter: DoSomething用户现在可以将回调指定为参数:

public void AnotherMethod()
{
    DoSomething(ShowSuccess); // ShowSuccess will be called when done
}

public void ShowSuccess()
{
    Console.WriteLine("Success!");
}

You can also use lamba expressions as a shorter way of writing your delegate: 您还可以使用lamba表达式作为编写委托的较短方式:

public void AnotherMethod()
{
    DoSomething(() => Console.WriteLine("Success!"));
    // Also DoSomething(delegate() { Console.WriteLine("Success!"); });
}

Callbacks are far from the only use cases for delegates. 回调远不是代表的唯一用例。 Hopefully this shows you some of their power: the ability to have code to be executed as a variable. 希望这能显示出它们的一些功能:能够将代码作为变量执行

Delegates allow you to treat functions as if they were any other variable. 代理允许您将函数视为任何其他变量。 A delegate type defines the signature of the function, that is, what the function returns, and the number and type of arguments that it takes: 委托类型定义函数的签名,即函数返回的内容,以及它所采用的参数的数量和类型:

// This is the delegate for a function that takes a string and returns a string.
// It can also be written using the framework-provided Generic delegate Func, as
// Func<String, String>
delegate String StringToStringDelegate(String input);

You can define a variable of this type, and assign it to an existing method. 您可以定义此类型的变量,并将其分配给现有方法。 I use the generic as an example, because that is the more common usage in .net since 2.0: 我使用泛型作为示例,因为这是自2.0以来在.net中更常见的用法:

String Reverse(String input) {
    return input.Reverse();
}

Func<String, String> someStringMethod = new Func<String, String>(Reverse);

// Prints "cba":
Console.WriteLine(someStringMethod("abc"));

You can also pass functions around this way: 您还可以通过这种方式传递函数:

String Reverse(String input) {
    return input.Reverse();
}

String UpperCase(String input) {
    return input.ToUpper();
}

String DoSomethingToABC(Func<String, String> inputFunction) {
    return inputFunction("abc");
}

var someStringMethod = new Func<String, String>(Reverse);

// Prints "cba":
Console.WriteLine(DoSomethingToABC(someStringMethod));

var someOtherStringMethod = new Func<String, String>(UpperCase);

// Prints "ABC":
Console.WriteLine(DoSomethingToABC(someOtherStringMethod));

In a big application it is often required to other parts of the application based on some condition or something else. 在大型应用程序中,基于某些条件或其他条件,通常需要应用程序的其他部分。 The delegate specifies the address of the method to be called. 委托指定要调用的方法的地址。 In simple manner a normal event handler implements the delegates in the inner layers. 以简单的方式,普通事件处理程序实现内层中的委托。

The oversimplified answer is that a delegate is basically a "pointer" to a block of code, and the benefit is that you can pass this block of code into other functions by assigning your block of code to a variable. 过于简单的答案是委托基本上是代码块的“指针”,并且好处是您可以通过将代码块分配给变量来将此代码块传递给其他函数。

The reason people relate Delegates to C function pointers is because this is in essence what delegation is all about, Ie: Pointers to methods. 人们将委托与C函数指针联系起来的原因是因为这实质上就是委托的全部内容,即:指向方法的指针。

As an example: 举个例子:

public void DoSomething(Action yourCodeBlock)
{
    yourCodeBlock();
}

public void CallingMethod()
{
    this.DoSomething(
    {
        ... statements
    });

    this.DoSomething(
    {
        ... other statements
    });
}

There are naturally lots of ways to invoke delegates as all of the tutorials will show you. 所有教程都会向您展示,有很多方法可以调用代理。 The point is though that it allows you to "delegate" functionality in such a way that you can call into methods without necessarily knowing how they work, but simply trusting that they will be taken care of. 关键是,它允许您以这样一种方式“委派”功能,即您可以调用方法而不必知道它们如何工作,而只是相信它们将被处理。 In other words, I might create a class that implements a "DoSomething()" function, but I can leave it up to someone else to decide what DoSomething() will do later on. 换句话说,我可能会创建一个实现“DoSomething()”函数的类,但我可以将其留给其他人来决定DoSomething()稍后会做什么。

I hope that helps. 我希望有所帮助。 :-) :-)

Delegates are a way to call back into your code when a long running operation completes or when an event occurs. 代理是一种在长时间运行的操作完成或事件发生时回调代码的方法。 For example, you pass a delegate to a method that asynchronously downloads a file in the background. 例如,您将委托传递给在后台异步下载文件的方法。 When the download is complete, your delegate method would be invoked and it could then take some action such as processing the file's contents. 下载完成后,将调用您的委托方法,然后可以执行某些操作,例如处理文件的内容。

An event handler is a special type of delegate. 事件处理程序是一种特殊类型的委托。 For example, an event handler delegate can respond to an event like a mouse click or key press. 例如,事件处理程序委托可以响应鼠标单击或按键等事件。 Events are by far the most common type of delegate. 事件是迄今为止最常见的代理类型。 In fact, you will typically see the event keyword used far more often in C# code than the delegate keyword. 实际上,您通常会在C#代码中看到事件关键字的使用频率远高于委托关键字。

You can think of it as a type in which you may store references to functions. 您可以将其视为可以存储对函数的引用的类型。 That way you can in effect, store a function in a variable so you may call it later like any other function. 这样你就可以将函数存储在变量中,这样你可以像以后任何函数一样调用它。

eg, 例如,

 public delegate void AnEmptyVoidFunction();

This creates a delegate type called AnEmptyVoidFunction and it may be used to store references to functions that return void and has no arguments. 这将创建一个名为AnEmptyVoidFunction的委托类型,它可用于存储对返回void且没有参数的函数的引用。

You could then store a reference to a function with that signature. 然后,您可以使用该签名存储对函数的引用。

public static void SomeMethod() { }
public static int ADifferentMethod(int someArg) { return someArg; }

AnEmptyVoidFunction func1 = new AnEmptyVoidFunction(SomeMethod);
// or leave out the constructor call to let the compiler figure it out
AnEmptyVoidFunction func2 = SomeMethod;
// note that the above only works if it is a function defined
// within a class, it doesn't work with other delegates

//AnEmptyVoidFunction func3 = new AnEmptyVoidFunction(ADifferentMethod);
                              // error wrong function type

Not only can it store declared functions but also anonymous functions (ie, lambdas or anonymous delegates) 它不仅可以存储声明的函数,还可以存储匿名函数(即lambdas或匿名委托)

// storing a lambda function (C#3 and up)
AnEmptyVoidFunction func4 = () => { };

// storing an anonymous delegate (C#2)
AnEmptyVoidFunction func5 = delegate() { };

To call these delegates, you can just invoke them like any other function call. 要调用这些委托,您可以像调用任何其他函数一样调用它们。 Though since it is a variable, you may want to check if it is null beforehand. 虽然它是一个变量,但您可能需要事先检查它是否为null

AnEmptyVoidFunction func1 = () =>
{
    Console.WriteLine("Hello World");
};
func1(); // "Hello World"

AnEmptyVoidFunction func2 = null;
func2(); // NullReferenceException

public static void CallIt(AnEmptyDelegate func)
{
    // check first if it is not null
    if (func != null)
    {
        func();
    }
}

You would use them any time you needed to pass around a method that you wish to invoke. 您可以在需要传递要调用的方法时使用它们。 Almost in the same way that you may pass instances of objects so you may do what you wish with them. 几乎与您传递对象实例的方式相同,这样您就可以按照自己的意愿行事。 The typical use case for delegates is when declaring events. 代表的典型用例是在声明事件时。 I have written another answer describing the pattern so you can look at that for more information on how to write those. 我已经写了另一个描述模式的答案 ,所以你可以看看它有关如何编写这些模式的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM