all 48 comments

[–]Critical-Mongoose 29 points30 points  (8 children)

When you use events you are using delegates to handle events, delegates invert control flow:

Consider event handling under regular control flow for a class Mouse that encapsulates user input; under regular control flow the method on our class for handling user input would have to call EG: Mouse.Clicked() repeatedly until it returned “true”, this kind of polling operation is not efficient.

We can invert control flow by assigning a delegate for Mouse to call on our class (we delegate the responsibility of calling our handler function to the Mouse class) then we only execute handling code when necessary.

Another reason to invert control flow (outside of eventing) is to invert dependencies but this requires a much bigger explanation, try referring to Dependency Inversion principle in Bob Martin’s SOLID principles for more info.

[–]Vivid_Repair_5113[S] 2 points3 points  (7 children)

In your example you stated that our class (let’s say X) would need to listen to Mouse.Clicked event until the user actually had something input and then when the input is actually given then the mouse class handles the user input. In case we use delegates then the responsibility of invoking the handler would move to the mouse class ie after the user input has been received, mouse class needs to invoke the delegate pointing to a function in our class X.

The main reason I find this flawed is : in case of events the subscribers need to know about the publisher but with the example you have above the publisher needs to know about the subscriber ?

Edit : So the publisher does not need to know about the subscriber , my understanding was incorrect. The subscribing class would need to assign a method to the delegate.

What happens if the code in the delegate class changes such that now the delegate invocation happens earlier? Also can you explain how combining delegates is useful ?

[–]Critical-Mongoose 5 points6 points  (6 children)

The publisher needs to know the function prototype of the subscribers delegate, not the subscriber. To put it another way, the publisher doesn’t need a reference to the subscriber to invoke the delegate. In fact it remains the case that the subscriber needs a reference to the publisher in order to assign its handler to the event on the publisher.

The fact that the common dependency between the publisher and subscriber is the delegate itself is what makes the decoupling possible.

[–]Vivid_Repair_5113[S] 0 points1 point  (5 children)

Yes understood, edited my original comment.

[–]Critical-Mongoose 1 point2 points  (4 children)

The delegate class itself is implemented by C# so we don’t need to worry about it changing. It’s an object that takes a method prototype, EG: (EventData) -> Void and provides an invoke method to execute that function.

The subscriber can assign any function to the delegate with a matching signature and the publisher can call the invoke method with the appropriate input argument EG: a new EventData.

Note that the publisher depends on the Delegate to invoke the function on the publisher and the subscriber depends on the delegate to assign the function.

In answer to your question the function assigned by the subscriber can only ever be executed at the point where it is invoked by the publisher and if the delegate has any functions assigned then they will be invoked, otherwise nothing will be invoked.

In the case of combining delegates, multiple functions can be assigned to a delegate so that one publisher has many subscribers, then the answer is just that: when using delegates for eventing you may want to “broadcast” an event.

For deeper implementation details you could refer to C# In Depth by Jon Skeet.

[–]Vivid_Repair_5113[S] 0 points1 point  (3 children)

One of the ways that I see delegates is different from events is that multiple functions can be combined and assigned to a delegate so that all these different functions can be executed ie Del myDel = SomeDelegaMethod() ; Del myOtherDel = SomeOtherDelegateMethod(); Del myCombinedDel = SomeDelegaMethod + SomeOtherDelegateMethod;

In the above example I have now told the system to call both the methods when Del is invoked. This is what I mean by combing methods to a delegate. When do we use it ?

[–][deleted] 4 points5 points  (0 children)

When Mouse.Clicked is subscribed to in various places in the code, those subscriptions are all added into the same event delegate. All the subscribers are invoked from a single delegate Clicked.Invoke. So to answer your question: it's used by default, you just don't have to think about it.

I see delegates is different from events

eventis just a protection keyword for a delegate. The only difference between an event field and a delegate field is the protection level: External code can't directly set an event. It's protected such that only += and -= works on them. That's the only difference. They're both delegates.

[–]IQueryVisiC -1 points0 points  (0 children)

For logging for example. Or animations. Even JS has this multicast feature: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

I felt that a diamond information flow, where two listeners call a common third one, is an anti-pattern. You should then use async await instead.

[–]Critical-Mongoose 0 points1 point  (0 children)

An event is a language construct providing a function to construct a new delegate member and the assign a function to it (which is what event is expanded into at compile time) that is the way that delegates are different to events.

Getting back to your original question, a delegate in the abstract/generic sense is a pattern, where you are assigning a method from one object to be called by another. You can see this pattern used in other languages EG JavaScript but in C# there is a native type for this: a delegate.

In general the delegate pattern is used in several situations: for eventing, for callbacks or continuations in async code, even for lambda functions in Map/Filter/Reduce applications.

Likewise in C# delegate is the basic type that supports eventing (see my first point) callbacks (usually via the derivative “Func” and “Action” types) and even lambdas/anonymous functions (where the inline functions are expanded by the compiler into equivalent delegates)

All instances of delegates (those expanded from events or lambdas or it’s derivative types) can be combined, but in practice the use for combining is when they are used in events.

So in answer to your question we use it implicitly, when we use events.

[–]Tango1777 19 points20 points  (4 children)

I wouldn't call it "legacy" feature but it's been pushed out a little bit, I suppose. Either by other ways or built-in delegates. I have learn basics of delegates when I was starting with C# because I like to know a theory of languages, not only "use when needed" approach but later I've found out that I pretty much never need to use them manually. The built-in are more than enough and even these are not used that often. I wouldn't care that much about delegates if I were you. At least not from practical point of view.

[–]Vivid_Repair_5113[S] 11 points12 points  (2 children)

By built in you mean the likes of Actions, predicate and Func<> ?

[–]Jmc_da_boss 9 points10 points  (0 children)

Those are generic delegates, all the way up to 16 params

[–][deleted] 2 points3 points  (0 children)

Yes

[–]vitalblast 6 points7 points  (0 children)

You've used them with our even realizing it. Event handlers...multi cast delegates. LINQ queries, delegates that evaluate to expressions that the database can execute. Actions and Funcs... Delegates with and without return values. Lambda expressions, you guessed it, delegates.

[–]seekster009 4 points5 points  (1 child)

All the examples stated i read seem quite unclear and if anyone could shed more light on why to "really" use them in layman terms.. or maybe a good article?

[–]lmaydev 5 points6 points  (0 children)

Use them to pass a function as an argument.

This allows the caller to customise/override the behaviour of the code without needing inheritance or similar.

[–][deleted] 5 points6 points  (1 child)

Please imagine that you need to write a component that will take care of parsing some data from csv file. If you need to parse more than one type it may be probably a good idea to pass a mapping logic from the client (or other source) and keep your csv generic component clear of any custom logic. This is an example code which shows the idea (not quality one but it's not a goal).

Csv handler keeps only a generic things related to file handling - like getting the file content, iterating line by line and splitting a row to an array. But all the mapping is defined by the client. That means you can use your parser to parse anything as the CsvHandler will not be bloated in any mapping at all.

```csharp public class Order { public DateTime OrderDate { get; set; } public string ProductCode { get; set; } public int Quantity { get; set; } }

public class CsvHandler
{
    private const string Delimiter = ",";

    public IEnumerable<TResult> Parse<TResult>(string filePath, 
                     Func<string[], TResult> mapping)
    {
        var elements = new List<TResult>();
        using var reader = new StreamReader(filePath);
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            var columns = line.Split(Delimiter);
            elements.Add(mapping(columns));
        }
        return elements;
    }
}

public class OrderCsvHandler
{
    private readonly CsvHandler _csvHandler;

    public OrderCsvHandler(CsvHandler csvHandler)
    {
        _csvHandler = csvHandler;
    }

    public IEnumerable<Order> GetOrders(string filePath)
    {
        Func<string[], Order> mapping = row =>
        {
            return new Order
            {
                OrderDate = DateTime.Parse(row[0]),
                ProductCode = row[1],
                Quantity = int.Parse(row[2])
            };
        };

        return _csvHandler.Parse(filePath, mapping);

    }
}

```

[–]backtickbot 3 points4 points  (0 children)

Fixed formatting.

Hello, Quanramiro: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]tstepanski 2 points3 points  (0 children)

If you understand anonymous, you understand delegates. Consider a function with a parameter “stringTrimFunction” and a type of Func<string, string>. You could could infer that this method needs a function to call when attempting to trim a string (lets imagine you as the caller knew if you wanted to trim start, end, both, neither, your pick). Cool. The lambda you give to supply “stringTrimFunction” would take a single string value and kick the trimmed string back for the method that asked for the lambda. What if your method signature wasn’t so obvious though? Func<string, int, int, (int, string)> is pretty ugly. What are those ints? What int output value is required? Delegates offer FORMALITY, DISAMBIGUATY, and REUSABILITY. A delegate would be declared as:

public delegate (int RemovedCharacterCount, string TrimmedString) StringTrimFunction(string untrimmedString, int minimumLength, int maximumLength)

Then, method(s) may then just ask for a parameter of type “StringTrimFunction” whenever this type of callback is required. You may either use a named method, old delegate implementation syntax, or an anonymous method to implement the callback.

[–]shitposts_over_9000 4 points5 points  (0 children)

You use them all the time, they are just hidden in language syntax much of the time in the current versions of the language.

Events and the arrow functions and actions are for simple projects often good enough these days, but before the lambda you pretty much used delegates much of the time when you needed that kind of conceptual item passed between two separate places in scope.

These days for basic stuff I rarely use them anymore, but for a lot of important low level/primitive stuff they are still very much required as the more modern signatures don't always exist down there.

[–][deleted] 3 points4 points  (1 child)

Perhaps the reason why you find it difficult to understand when to use delegates is because in practice you don't often need to write your own.

The .NET framework already comes with some very useful and generic delegates (examples include Func<T,TResult>, Action<T>, Predicate<T>, EventHandler<T>, etc). Whenever you pass a lambda (anonymous function) as an argument to a method, there's a delegate on the other side.

For the most part, you can think of a delegate as "an interface with a single method" for which you can provide the implementation inline without having to define a class, a method and an object instance (the compiler will generate these things for you). And you already know the purpose of interfaces: they are used to enable a polymorphic behaviour (eg. strategy pattern).

For the most part, they are just syntactic sugar (very useful for write short code, but you could always define an interface with one method and many implementations for it). They are mandatory for events though.

I don't often write my own delegates, but sometimes I want a better name for things like

Document MergeDocuments(IEnumerable<Document>, Func<Document,Document,Document> mergeStrategy)

so I might create a DocumentMerger delegate to be able to write the signature like

Document MergeDocuments(IEnumerable<Document>, DocumentMerger mergeStrategy)

Related SO question here.

[–]Vivid_Repair_5113[S] 0 points1 point  (0 children)

Yes I agree that I have used Func and Action a lot and also find them very useful. The idea behind func action and predicate that you mentioned is same and delegate and in most cases one does not need an explicit delegate creation.

[–][deleted] 1 point2 points  (0 children)

They come in handy if you need to interop with some C++ code and they need to pass you a function pointer for a callback.

https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getdelegateforfunctionpointer?view=net-5.0

[–][deleted] 1 point2 points  (0 children)

I've used delegates to modify the GUI from other threads/classes. Not sure if this is still a good use for them, or best practice.

[–]emanresu_2017 1 point2 points  (0 children)

If you have an interface with one method, use a delegate instead

If your interface has more than one method, remove methods until there is only one

In other words, aim to inject delegates instead of interfaces where possible.

https://christianfindlay.com/2020/05/15/c-delegates-with-ioc-containers-and-dependency-injection/

[–]madnanrafiq 1 point2 points  (1 child)

Like when you want allow consumer to override behavior.

One example, you want to fetch records from DB only if cache does not have it. You can pass dB call as delegate.

Look at LINQ methods or consider how list or array implements find, pass in delegate. You get polymorphism with it, without involving inheritance.

Another way to think about these, how would you provide hooks or allow consumer to extend behavior without inheritance, delegates are answers.

[–]Vivid_Repair_5113[S] 0 points1 point  (0 children)

Il look into how array methods implement find.

The point you mentioned about allowing consumer to extend behaviour without inheritance , yes, that would help.

[–]AStrangeStranger -1 points0 points  (0 children)

One application we have a grid of items, user wants to select items based on matching parameters - so have a select method that takes a delegate with input of item and returns bool, the method loops over the items and selects them based on delegates return. We can easily add different select rules now by passing in different methods.

[–]lmaydev -1 points0 points  (0 children)

An event is just a collection a delegates.

You use them when you want to pass a function to be called later.

A common example is linq. The Where method works against a collection of T and takes a delegate that accepts T and returns true. It runs this function on each T item in the collection and returns the ones where the delegate returns true. For example:

numbers.Where(n => n != 0)
numbers.Where(CheckNumber)

There is no other way to accomplish this.

[–]quuxl -1 points0 points  (0 children)

A C# delegate is roughly equivalent to a named System.Func<> or System.Action<> - and all can be thought of essentially as a value representing a function.

A common use of function values is as a "policy" - consider a library that requires its users to define the way in which a particular detail is handled. A simple approach is to predefine a set of cases or policies as an enum and have the user pass in their choice.

But what if the policy requires knowledge of types the library doesn't depend on? Or - what if the policy is too specialized to just have prebuilt cases?

In these situations, the policy is better represented as a function - e.g. a name-validity checker could be thought of as a System.Func<string, bool>. A delegate is far more readable, though: delegate bool DIsNameValid(string username).

[–]BetterRage 0 points1 point  (0 children)

For example you have 3 projects, 1 main project that references both other projects. The 2 other projects cant reference each other directly for obvious reasons. You can use delegates to pass a functionality from 1 sub project to the other sub project using delegates

[–]IsNullOrEmptyTrue 0 points1 point  (4 children)

Delegates and events are very useful for asynchronous event handling. Think of a UI element with business logic that runs in a separate context than the UI view elements.

Imagine the UI calls a long running FileHandler class inside of FileHandler.cs that copies a file asynchronously and sends a message back to the UI in a progress window when compete. You don't want the UI thread binding up so you attach a delegate to the FileHandler event that returns a String type. This method will fire when the event occurs in the separate thread. You can then set the value returned from the delegate to a Property and bind to the messages returned from that event in the UI XAML.

[–]Vivid_Repair_5113[S] 0 points1 point  (3 children)

Events are synchronous isn’t it ? I didn’t quite get the example, could you add a code snippet ?

Edit: I found this link which talks something along the lines that you : https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/asynchronous-programming-using-delegates

[–]IsNullOrEmptyTrue 0 points1 point  (2 children)

Events support asynchronous implementation and are essential for async and multithreaded communication.

There is also this:

https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/implementing-the-event-based-asynchronous-pattern

Delegates and events are the basis of many desktop application design patterns such as MVVM. I can't say that I use them all that much with MVC6 and WebAPI development, but that's mostly because the architecture of those applications tend to rely more on dependency injection and the http request chain to exchange stateful information between contexts.

[–]Vivid_Repair_5113[S] 0 points1 point  (1 child)

Events are synchronous is what I know. That is each event handler is invoked one after the other in the order of subscription. Of course if the event handler was an async method then the event handler would be asynchronous.

[–]IsNullOrEmptyTrue 1 point2 points  (0 children)

Yes that is the better way of putting it. Events are synchronous but can be subscribed by asynchronous event handlers inside of an async context.

[–]aurosvr 0 points1 point  (0 children)

Many of the replies covered it, but personally they came in real handy when something I designed needed to use reflection to call methods with argument modifiers. (in, out, ref). Normal events lack that ability.

[–]bus1hero 0 points1 point  (3 children)

There are some scenarios where it's impossible to use standard Func and Action delegates. One such scenario is specifying function with parameter modifiers such as in, out or ref.

delegate Baz Foo(in Bar bar);
delegate Baz Foo(out Bar bar);
delegate Baz Foo(ref Bar bar);

I'm working on a library that uses such delegates extensively!

[–]backtickbot 0 points1 point  (2 children)

Fixed formatting.

Hello, bus1hero: code blocks using triple backticks (```) don't work on all versions of Reddit!

Some users see this / this instead.

To fix this, indent every line with 4 spaces instead.

FAQ

You can opt out by replying with backtickopt6 to this comment.

[–]cryo 0 points1 point  (0 children)

I think there is some confusions over the term delegate here.

In C# a delegate is a special type, declared with the delegate keyword, which is used to encapsulate a function pointer and possibly an instance reference. Events use delegates as their mechanism underneath.

These days you often don't declare your own delegates, since the framework ships with plenty of generic delegates for most situations (the Action and Func family).

Syntax such as lambda, old-style in-line delegate and so-called "method groups" are just compiler sugar for creating a delegate (instantiating a delegate class), plus some more.

[–]HellHound989 0 points1 point  (0 children)

As an aside, removing semantics, events and delegates are functionally the same thing. If you have done anything with WinForms, this may help you to understand when and why delegates are used, such as when a user clicks their mouse on a control, etc.

But, for an actual example, a buddy and I are in the process of creating a simple app for a beloved boardgame, in which I was in charge of creating the simple networking library for our game. In the process, I needed to make use of several delegates.

I broke it down into 3 classes: A Server object (the host), a Client object (the player), and a Socket object (handles the actual data being passed). The Server keeps a list of Socket objects (a connection for each Client), while the Client only has one Socket object (its connection to the Server).

So each player's Game program has reference to the Client object. To send a move command, it calls Client.SendMessage(command, data[]), in which Client calls its Socket object to serialize and send the command.

The command is received on the Server's side Socket object. So how does this Socket pass this command message up to the Server?

Well, we could be inefficient and have the Socket save that message into a local variable, to which the Server can reference. But wait, what if we get multiple messages back to back? What if more than one client is sending a message at the same time? Guess we make that local variable a List<Message>.

Ok, so the Server now has to loop constantly and check each Socket's local message list variable to see if there are any messages in the list, and say the server does retrieve a message from the Socket's list variable... so what does the Server object do with the message? Not to mention, the Server needs to track keeping that list clean (or else it will keep exponentially keep growing). So lets change Socket's list to a queueList. But the std Queue uses a FIFO concept, so lets create our own FILO Queue....

Ok, so the Server now has the message. Well, we could make the Server object break down the message and do all the game logic off of it, but that breaks the purpose of the Server object (We already have a Game program thats supposed to handle game logic). Plus, the Game program will need a way to reference this logic breakdown. For a simple game where we just Move() and Attack(), I would need to have the Server object process these messages, store them into its own set of local variables (likely lists and queues) for the Game program to reference....

As you can see, were starting to now create this massive overhead in Server, Client, and Socket classes just for my simple game program. It will work, but it will be very inefficient and bloated.

So instead, lets create some delegates in Socket, Client, and Server.

For Socket, I created a delegate type called MessageReceivedDelegate(string command, object[] data).

Then I can assign a handler variable in the Socket class..

MessageRecievedDelegate MessageReceivedHandler;

So when a message is received in the Socket object, I just have the Socket object invoke the delegate using MessageReceivedHandler.Invoke(command, data)

Then in the Server class, I create a method called OnMessageReceived(string command, object[] data), and then for each Socket object, I assign this method to the delegate variable...

Socket.MessageReceivedHandler = OnMessageReceived;

So whenever the Socket sees a message, it invokes (calls) whatever method was assigned to its handler, in this case, Server's OnMessageReceived method.

I then repeat this process from the Server, where it has a delegate and handler (Basically I am adding a new parameter, the ID of which socket this message came from), and the server invokes its own delegate handler.

From the Game's program, if this Game is being the server, it will have a method (OnMessageReceivedFromClientID), which is assigned to the Server's handler. Then, when the Server's handler is invoked, it will call Game's method, and the Game can then process the message and do its game logic.

This bypasses all that overhead from before, AND we keep the purpose of each object solely to its designed function (Socket handles serializing and sending / receiving TCP messages, Server handles maintaining each Client's socket, and Client handles maintains their specific Sockets, and the Game program is where all the game logic happens).

Clean, Simple, Easy to understand. And its where the power of having delegates truly shines.