Uses of delegates in C# (or other languages)

2019-03-27 17:56发布

I have always wondered how delegates can be useful and why shall we use them? Other then being type safe and all those advantages in Visual Studio Documentation, what are real world uses of delegates.

I already found one and it's very targeted.

using System;

namespace HelloNamespace {

    class Greetings{
    public static void DisplayEnglish() {
            Console.WriteLine("Hello, world!");
    }
    public static void DisplayItalian() {
             Console.WriteLine("Ciao, mondo!");
    }
    public static void DisplaySpanish() {
             Console.WriteLine("Hola, imundo!");
         }
    }

    delegate void delGreeting();

    class HelloWorld {
        static void Main(string [] args) {

    int iChoice=int.Parse(args[0]);
    delGreeting [] arrayofGreetings={
             new delGreeting(Greetings.DisplayEnglish),
             new delGreeting(Greetings.DisplayItalian),
             new delGreeting(Greetings.DisplaySpanish)};

    arrayofGreetings[iChoice-1]();
         }
    }
}

But this doesn't show me exactly the advantages of using delegates rather than a conditional "If ... { }" that parses the argument and run the method.

Does anyone know why it's better to use delegate here rather than "if ... { }". Also do you have other examples that demonstrate the usefulness of delegates.

Thanks!

11条回答
冷血范
2楼-- · 2019-03-27 18:10

Here's a real world example. I often use delegates when wrapping some sort of external call. For instance, we have an old app server (that I wish would just go away) which we connect to through .Net remoting. I'll call the app server in a delegate from a 'safecall ' function like this:

private delegate T AppServerDelegate<T>();

private T processAppServerRequest<T>(AppServerDelegate<T> delegate_) {
           try{
              return delegate_();
           }
           catch{
              //Do a bunch of standard error handling here which will be 
              //the same for all appserver  calls.
           }

        }

//Wrapped public call to AppServer
public int PostXYZRequest(string requestData1, string requestData2, 
   int pid, DateTime latestRequestTime){
           processAppServerRequest<int>(
              delegate {
                 return _appSvr.PostXYZRequest(
                    requestData1, 
                    requestData2, 
                    pid, 
                    latestRequestTime);  
              });

Obviously the error handling is done a bit better than that but you get the rough idea.

查看更多
迷人小祖宗
3楼-- · 2019-03-27 18:10

Delegates are used to "call" code in other classes (that might not necessarily be in the same, class, or .cs or even the same assembly).

In your example, delegates can simply be replaced by if statements like you pointed out.

However, delegates are pointers to functions that "live" somewhere in the code where for organizational reasons for instance you don't have access to (easily).

查看更多
太酷不给撩
4楼-- · 2019-03-27 18:11

Lambda expressions
Delegates were mostly used in conjunction with events. But dynamic languages showed their much broader use. That's why delegates were underused up until C# 3.0 when we got Lambda expressions. It's very easy to do something using Lambda expressions (that generates a delegate method)

Now imagine you have a IEnumerable of strings. You can easily define a delegate (using Lambda expression or any other way) and apply it to run on every element (like trimming excess spaces for instance). And doing it without using loop statements. Of course your delegates may do even more complex tasks.

查看更多
Anthone
5楼-- · 2019-03-27 18:13

In your example your greating are the same, so what you actually need is array of strings.

If you like to gain use of delegates in Command pattern, imagine you have:

public static void ShakeHands()
{ ... }

public static void HowAreYou()
{ ... }

public static void FrenchKissing()
{ ... }

You can substitute a method with the same signature, but different actions. You picked way too simple example, my advice would be - go and find a book C# in Depth.

查看更多
叛逆
6楼-- · 2019-03-27 18:16

The most common real-world everyday use of delegates that I can think of in C# would be event handling. When you have a button on a WinForm, and you want to do something when the button is clicked, then what you do is you end up registering a delegate function to be called by the button when it is clicked.

All of this happens for you automatically behind the scenes in the code generated by Visual Studio itself, so you might not see where it happens.

A real-world case that might be more useful to you would be if you wanted to make a library that people can use that will read data off an Internet feed, and notify them when the feed has been updated. By using delegates, then programmers who are using your library would be able to have their own code called whenever the feed is updated.

查看更多
走好不送
7楼-- · 2019-03-27 18:24

Delegates are simply .Net's implementation of first class functions and allow the languages using them to provide Higher Order Functions.

The principle benefit of this sort of style is that common aspects can be abstracted out into a function which does just what it needs to do (for example traversing a data structure) and is provided another function (or functions) that it asks to do something as it goes along.

The canonical functional examples are map and fold which can be changed to do all sorts of things by the provision of some other operation.

If you want to sum a list of T's and have some function add which takes two T's and adds them together then (via partial application) fold add 0 becomes sum. fold multiply 1 would become the product, fold max 0 the maximum. In all these examples the programmer need not think about how to iterate over the input data, need not worry about what to do if the input is empty.

These are simple examples (though they can be surprisingly powerful when combined with others) but consider tree traversal (a more complex task) all of that can be abstracted away behind a treefold function. Writing of the tree fold function can be hard, but once done it can be re-used widely without having to worry about bugs.

This is similar in concept and design to the addition of foreach loop constructs to traditional imperative languages, the idea being that you don't have to write the loop control yourself (since it introduces the chance of off by one errors, increases verbosity that gets in the way of what you are doing to each entry instead showing how you are getting each entry. Higher order functions simply allow you to separate the traversal of a structure from what to do while traversing extensibly within the language itself.

It should be noted that delegates in c# have been largely superseded by lambdas because the compiler can simply treat it as a less verbose delegate if it wants but is also free to pass through the expression the lambda represents to the function it is passed to to allow (often complex) restructuring or re-targeting of the desire into some other domain like database queries via Linq-to-Sql.

A principle benefit of the .net delegate model over c-style function pointers is that they are actually a tuple (two pieces of data) the function to call and the optional object on which the function is to be called. This allows you to pass about functions with state which is even more powerful. Since the compiler can use this to construct classes behind your back(1), instantiate a new instance of this class and place local variables into it thus allowing closures.

(1) it doesn't have to always do this, but for now that is an implementation detail

查看更多
登录 后发表回答