C
C#2mo ago
zzzz

When should one use a custom delegate instead of Func/Action/Predicate?

Title.
80 Replies
Evyr
Evyr2mo ago
It's a good way to make sure people aren't doing silly things. If you use Func/Action then you can pass anything with the same parameters and return type, even though it could do something wildly different. Restricting arguments to a specific type of delegate means whoever's using that function has a sanity check to make sure they're not misusing it Func/Action/Delegate are also part of the base class library whereas delegate is just a part of the language, though I can't think of many situations where that'd matter Oh when, not why, sorry Though the same logic applies
Angius
Angius2mo ago
Func and Action are very simple. Those are the types I expect as input, this is (or isn't) the type I will give as an output. Delegates can be generic, can have named parameters, can have ref parameters, pretty sure out as well
Sossenbinder
Sossenbinder2mo ago
Custom delegates also allow optional arguments, and I sometimes like to use them because naming them is often helpful for readability So instead of an Action<T> I could have a "XXXCallback" in the codebase
zzzz
zzzzOP2mo ago
What about using the Delegate type directly?
Angius
Angius2mo ago
Never used it
zzzz
zzzzOP2mo ago
like this
No description
Angius
Angius2mo ago
Makes no sense to me over using an Action<string> It smells of using an object or dynamic that's basically "whatever lmao"
Evyr
Evyr2mo ago
Delegate is the base class for Func and Action iirc
zzzz
zzzzOP2mo ago
i thought they were defined using the delegate keyword i understand that but isnt that the same as Action<T>? they're both generic
Evyr
Evyr2mo ago
Func and Action are delegate types in the base class language and are delegates, the delegate keyword defines a new delegate
Angius
Angius2mo ago
Action<int> will take only a void method that takes one single int parameter Delegate will take anything void Foo(int x)? Sure. string Bar(int a, int b, Person c)? Why not (int a, string b, Func<int, Person> c) Baz(IQueryable<Dictionary<string, int>> quaz)? Sure, fuck me up
zzzz
zzzzOP2mo ago
well handleEvent("click", callbackgoeshere) what if i want literally any callback I dont really wanna impose a restriction
Angius
Angius2mo ago
How do you reason about it? When you invoke it, what do you give it as parameters?
zzzz
zzzzOP2mo ago
i want to let the user handle the event hwoever they want? if the click event gets fired they can chose any behavior they want
Angius
Angius2mo ago
What do you expect in return?
zzzz
zzzzOP2mo ago
they could launch a new process. they could print to the console. they could close the current process. idk
Angius
Angius2mo ago
Right, so, the user passes a delegate with this signature:
(int a, string b, Func<int, Person> c) Baz(IQueryable<Dictionary<string, int>> quaz)
(int a, string b, Func<int, Person> c) Baz(IQueryable<Dictionary<string, int>> quaz)
how do you invoke it?
zzzz
zzzzOP2mo ago
delegate.Method.Invoke()?
zzzz
zzzzOP2mo ago
No description
Angius
Angius2mo ago
And what parameters you give it, if it can be anything?
zzzz
zzzzOP2mo ago
well Invoke takes object[] so anything... not sure how to answer that
Angius
Angius2mo ago
Yeah, and what will be inside of it? Exactly The user can still do anything they want inside of an Action No parameters, void return type It still captures outside variables, for example
zzzz
zzzzOP2mo ago
sure, i understand that
zzzz
zzzzOP2mo ago
i see action has some syntactic sugar to let you invoke it as if it was a method
No description
Angius
Angius2mo ago
Yep
surf68
surf682mo ago
plus, Delegate doesn't actually give you a free-for-all, you just get a runtime error if the arguments don't match those expected by the actual argument provided so you're essentially breaking out of the type system for zero gain in much the same way as passing objects around
zzzz
zzzzOP2mo ago
are you two acquainted with object.addEventHandler in JS?
surf68
surf682mo ago
yes
Angius
Angius2mo ago
What it expects is a function that takes an Event and returns nothing So an Action<Event> in C# terms
zzzz
zzzzOP2mo ago
the way this works is that object.addEventHandler(eventName : string, callback : Function) will add the callback instead of overwriting. Meaning that you can do that multiple times for multiple functions and trigger all of them when the event fires Is this what multicasting is in C#?
Angius
Angius2mo ago
What you're looking for is events, then Or just a list of Actions you can keep adding to and execute them in a loop
zzzz
zzzzOP2mo ago
I dont quite get this then
No description
surf68
surf682mo ago
multicast delegates aren't quite the same as event handlers, no
Angius
Angius2mo ago
Uh, I guess another weirdness of Delegates...?
Evyr
Evyr2mo ago
You're casting multiple methods to the delegate type, then when you invoke that delegate it sequentially invokes each method assigned to it
Angius
Angius2mo ago
I won't be of much help here, I literally never seen bare Delegate used anywhere
surf68
surf682mo ago
multicast delegates are essentially like adding multiple delegates together so that you can refer to the invocation of both (in the case of two) in one place
Evyr
Evyr2mo ago
you can do events that way, but C# has a convention with events using the event keyword Because all delegates have invocation lists, not just events the convention is you define your delegate type for the event, say
delegate void MyEventDelegate(object sender, MyEventArgs e);
event MyEventDelegate MyEvent;
delegate void MyEventDelegate(object sender, MyEventArgs e);
event MyEventDelegate MyEvent;
then you can subscribe to that event
surf68
surf682mo ago
you can have a multicast delegate without having anything to do with events, whereas addEventListener is specific to events on an instance
zzzz
zzzzOP2mo ago
nah this is also applicable to Actions
Evyr
Evyr2mo ago
but you can just as well have MyEventDelegate MyEvent on its own and subscribe to it, you just won't have a couple of extra protections, bells and whistles that come with events specifically
zzzz
zzzzOP2mo ago
from what i understand i can do
Action a = method1 + method2 + method3;
Action a = method1 + method2 + method3;
and when the delegate gets invoked as a callback it will execute the three methods in order, correct?
Evyr
Evyr2mo ago
When you invoke any delegate type, whether it be Func, Action, Delegate, Event, etc it just invokes every method added to its invocation list sequentially, and if that delegate type has a return type, it returns the result of the last delegate in its invocation list Correct, yeah
zzzz
zzzzOP2mo ago
got it
Evyr
Evyr2mo ago
if that was Func a = func1 + func2 + func3; with a return type, it'll return the result of func3 only, not a sum of them, but 99% of the time that doesn't matter
zzzz
zzzzOP2mo ago
why are people saying that events should be avoided and only delegates should be used?
zzzz
zzzzOP2mo ago
Nick Chapsas
YouTube
Are events in C# even relevant anymore?
Check out my courses: https://dometrain.com Become a Patreon and get source code access: https://www.patreon.com/nickchapsas Hello everybody I'm Nick and in this video I will explain why I think that events as a feature in C# is obsolete and how we can implement the same event-like mechanism in a modern and elegant way. Timestamps Intro - 0:00...
Angius
Angius2mo ago
For content
zzzz
zzzzOP2mo ago
ic
surf68
surf682mo ago
honestly, beats me. you can use delegates in a similar way to events but there are distinct differences.
zzzz
zzzzOP2mo ago
i was wondering if there was any merit to this
surf68
surf682mo ago
to me that video is pure bunk. someone linked it earlier as reasoning behind abandoning events and the conclusion of that video is to use MediatR. it's wild.
zzzz
zzzzOP2mo ago
alright, so i'm a typescript/angular dev right. you would use C# events/delegates if you wanted to implement the subscriber/observer pattern?
surf68
surf682mo ago
not that there's anything wrong with MediatR but you certainly wouldn't use it in a lot of cases you'd use events.
zzzz
zzzzOP2mo ago
if i recall its called something else in the C# world, publisher/subscriber i think
surf68
surf682mo ago
if you're used to JS events, they're pretty much a direct analogue
zzzz
zzzzOP2mo ago
i see do people use libraries for this kinda stuff?
surf68
surf682mo ago
there's just some syntactic sugar around adding/removing event handlers
zzzz
zzzzOP2mo ago
is rx a thing in the C# ecosystem
surf68
surf682mo ago
i.e. x.addEventListener("click", () => { ... }) becomes x.Click += () => {...}
zzzz
zzzzOP2mo ago
that is oddly wpf'esque I remember trying to make a WPF desktop application when i was younger, i remember doing that for some buttons. little did i know i was using delegates this whole time
surf68
surf682mo ago
well they're events but yes, events are delegates with some additional rules
zzzz
zzzzOP2mo ago
yeah i hate the world
No description
surf68
surf682mo ago
what's there to hate?
zzzz
zzzzOP2mo ago
but hold on i can use the delegate keyword to create anonymous methods? why has no one told me this
Action<string> a = delegate (string s) { Console.WriteLine(s); };
Action<string> a = delegate (string s) { Console.WriteLine(s); };
vs
Action<string> a = (string s) => { Console.WriteLine(s); };
Action<string> a = (string s) => { Console.WriteLine(s); };
are both of these "anonymous methods"?
Evyr
Evyr2mo ago
yeah they're both anonymous functions you could also do Action<string> = Console.WriteLine in this case
zzzz
zzzzOP2mo ago
I think you can only do that if the method group has only one overload in this case it might be confused as to which WriteLine you're talking about unless it infers it from the <string>?
surf68
surf682mo ago
they're both anonymous methods
zzzz
zzzzOP2mo ago
can confirm, it does infer it it's only an issue if you do
var write = Console.Write; // ERROR: Multiple overloads, can't choose
var write = Console.Write; // ERROR: Multiple overloads, can't choose
Uchiha Wick
Uchiha Wick2mo ago
someone could help me with a save botton?
surf68
surf682mo ago
syntax in the second came about in a later version of C#
zzzz
zzzzOP2mo ago
they are called lambdas?
surf68
surf682mo ago
lambda expressions, yeah
zzzz
zzzzOP2mo ago
is it necessary to instanciate a delegate type? what's the difference between
myDelegate md = myMethod
myDelegate md = myMethod
and
myDelegate md = new myDelegate(md);
myDelegate md = new myDelegate(md);
surf68
surf682mo ago
no difference
zzzz
zzzzOP2mo ago
thank you
surf68
surf682mo ago
anyhow I'm off, good luck in your delegate travels
zzzz
zzzzOP2mo ago
<3 take care
Evyr
Evyr2mo ago
if you're using += then yes, but if you're assigning to md then no
Joschi
Joschi2mo ago
Multicast delegates is how events are implement in C# as far as I know. Delegates are not that often used, but they are valuable if you go deeper into the functional style of C#. https://www.youtube.com/watch?v=2TXvwUgaMHs&t=1s
Zoran Horvat
YouTube
Master the Design of Functional Behavior in C#
How do we implement functions in a class-based programming language, such as C#? The latest C# programming language specification offers a rich syntax that supports functional programming in this versatile language. Functional design is known for its simplicity and the short code it produces compared to other design techniques we apply. It is ba...

Did you find this page helpful?