241 Replies
at a basic level, a delegate is a way to reference another method. Action<T>, Func<T>, etc are delegates
so if you wanted to make a method that takes in a method,
void MyMethod(Action yourMethod)
and does some logic, then calls yourMethod, that would be a use for a delegatea way to reference another method?
Use methods as parameters?
basically. Or variables
ok, and why would we want to use methods as parameters?
events are usually a good example. Imagine you have something like, in WinForms, OnFormShown. You can give it one of your methods, and whenever the form is shown, their internal logic calls your method
i donโt know what WinForms or OnFormShown is.
System.Linq has a bunch of methods that take delegates as parameters
what is System.Linq
Iโm a beginner, iโm mainly interested in knowing what it is and why it is used
A collection of methods that are generally centered around filtering collections
I don't know if we can simplify it much further ๐ it's if you want to pass a method to a method. Usually so that other method, which you probably don't control, can call your method at some later time instead of you calling it immediately
Like D.Mentia said above. A delegate is a pointer / reference to a function or method. Why its used? Implementations of the methods may differ but the expectation of its signature stays the same eg.
void Method(string hello)
(it returns nothing, and has 1 parameter)even in linq it's the same purpose,
bool myContains(string s) { return s.Contains("Hello")}
is the same thing shown above. At the time you give it to linq, you don't actually know what s is, so you can't just check right now. You have to give it the method, so it can give your method the string later, whenever it knows what it is
x => x.Contains("Hello")
is shorthand for defining that method, which you give to the linq .Where method, since .Where accepts a method as a parameter (a delegate/Func)so you call a method with another method?
you can yes
then you can do
wow this is veeeeeeery confusing haha
or even
MyMethod(Console.WriteLine)
because Console.WriteLine is a method that takes in a string and returns nothing, which is what Action<string> asks fortruee
It really shouldn't be, it's simply passing a method as a parameter. That's all it is
It allows you a lot of flexibility
It has the same restrictions as other parameters with regards to types etc
It does sound easy on paper, yes. Passing a method as a parameter. But our PP presentation are 50 brutal pages long so itโs impossible to learn
Haha
Don't worry, don't panic, slow down
arion
REPL Result: Success
Console Output
Compile: 446.832ms | Execution: 23.675ms | React with โ to remove this embed.
pardon my bad grammar there, but u can see what we mean right?
What is the action syntax?
An Action is a delegate of void return type
You know
List<T>
right?Iโve heard of it, yes
This is the same as list, but it's a delegate with no return type, instead of a collection. The type parameter is how you specify what parameters the method can take
Console.WriteLine takes a single string, so it matched the type
There's nothing really special about the Action / Action<T> delegate. You can write your own delegate that does the same thing
or generics
contravariance for brevity?
Ignore that bit
dont worry about that ;)
It's really hard to balance correctness with understandability at times ๐
:nod: otherwise u get moments of "Ackshually..."
Yuuuup
This is the example the show how it's used..
Still doesn't make any sense
If i have two methods subtract and add, why not just call them with the parameters x and y respectively?
That's just demonstrating how you use it
It's not an example of a good scenario to use it in
Most of the time, you use delegates to allow yourself or another programmer to have more flexibility when calling your methods
Like, I made a method that took a list of things and let the caller specify how to visualize each item via a delegate
This let me reuse my method everywhere, by just changing what I passed to the delegate
Or to be able to do something later, at a specific time or in a specific scenario, instead of right now
๐
Timers are probably a good example to use, you give them a method and say, run this in 10 seconds
Ok i'll just accept that i wont get it
Does Func<> and Action<> have anything to do with delegates?
Action<> and Func<>
Events and EventArgs
EventHandler<T>
Anonymous Methods
Lambda expressions
Anonymous types
Like i'm supposed to know all this
And there isn't really any YouTube videos or guide sthat explain these properly without it being convoluted or incomprehensible
Action and Func are just simple delegates that are already made for you. Somewhere in the MS code imagine there is
delegate void Action(string s)
, for all the different types, so there's Action(int s), etc.
except it's really just delegate void Action<T>(T s)
which makes it work for all types, and that's generic types... which isn't on your list but close enoughDelegates are closely related to events handlers
hahahhaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa๐ญ
what are you all even talking about
And anonymous methods and lambda methods
Bro you wrote the list
What list?
This
Yes?
And we said what parts of it delegates relate to
I'm just looking for a simple, unconvoluted explanation which a beginner can comprehend
This isn't a "beginner" topic
Like, not early beginnings at least
You need to grasp types and variables and methods before this makes any sense
delegate void Action(string s)
^ This I understand. We create a function of type delegate which returns nothing (void) and takes a string s as parameter.
delegate void Action<T>(T s)
This i do not understand? We Make a delegate which returns nothing(void) and the name of the delegate is Action<T>
???? And the parameters is of type T and variable name s?tbh, ChatGPT would be great at answering these
T is a "type parameter"
delegate void Action<whatever goes here>(gets_put_here s)
It's a part of generic types
Very important to understand
It's what makes most of C# type safe
Ok. So T = we don't know what type will be put in
Yeah, it's a placeholder
And Action?
is that a function?
It's your name
from CBL
Of the type
right. Then whenever you want to use it, you'd use it like
MyMethod(Action<int> yourAction)
if you want to take in a method that takes an int and returns nothingLook at your two examples
See how they are identical if not for the <T>
Ok so Action is just a name. I could put
delegate void Sad<T>(T s)
?Yes
Action is a pre-made delegate in the BCL
But if you make your own, you control the names
yup. Then
MyMethod(Sad<string> yourSadStringMethod)
I see.
Is there a difference between
delegate void sad(T s)
and delegate void sad<T>(T s)
?Yes, the first won't work
the <T> has to go there if you're using it inside the ()
It doesnt specify T as a type parameter
I see. So if i don't know what the parameters type will be we use the
Action<T>
?You would specify T somewhere
You use T during the declaration
Not during the usage
Right, so T during declaration of parameter but usage of arguments we use proper types such as int?
Yes
Look at List<T> as an example
When we make the class, we don't know what type the list is for
But when we make a new list, we say "this is a lost of strings!"
also it's worth mentioning that T is just a name, it can be
delegate void sad<TType>(TType s)
or sad<Tsadtype>(Tsadtype s)
or whatever, T is just what you usually use if there's only one. And usually you always make them start with T so it's not too confusing what it isdelegate int calculating<T>(T number1, T number2)
So if i declared a delegate like this.
And then made two methods for add and subtract.
int Add(int number 1, int number 2) { return number1 + number2 }
int Sub(int number 1, int number 2) { return number1 - number2 }
To use these methods we would do it like this...
int resultofAdd = calculating(Add)
int resultofSub = calculating(Sub)
Console.WriteLine(resultofAdd)
Console.WriteLine(resultofSub)
Am i thinking right?yes, but that's the same thing as
calculating<int>(Add)
. In some cases you would have to specify that <int>, but in this case it can figure out that it's <int> because Add takes in ints, so it's OK to leave it out like you didalso, in this case you have to start using generic type constraints
because the compiler doesn't know for sure that your T will have + and - operators
so what you said mostly works, but that's kinda getting more complicated too
I guess that means it's time to explain lambdas ๐
These are all the same thing:
int Add(int number1, int number2) { return number1 + number2;}
int Add(int number1, int number2) => number1 + number2;
calculating<int> Add = (int number1, int number2) => { return number1 + number2; }
calculating<int> Add = (int number1, int number2) => number1 + number2;
calculating<int> Add = (number1, number2) => number1 + number2;
(Also, all of those would also work as Func<int,int,int> Add = (number1, number2) => number1 + number2;
, because a Func is a method that takes in the first types and returns the last one)
Lambdas are the => that's shorthand for declaring methods, and you can skip the {} if you're just returning a single line of code
This is relevant because in your example, you could instead do int resultofAdd = calculating<int>((number1, number2) => number1 + number2)
, which is a scenario where you would actually need to give it the <int>. Or you could do int resultofAdd = calculating((int number1, int number2) => number1 + number2)
, and then it knows it's an int so you don't need <int>
so that's what I meant by you don't need the <int> with what you did, but only because the compiler knows it's ints because Add has int parametersIs the delegate supposed to be green?
yep
Yes VS colors them green by default.
Many keeps saying i should use TryParse instead of convert
int numbers = TryParse(Console.ReadLine());
How come that doesn't work?$tryparse
When you don't know if a string is actually a number when handling user input, use
int.TryParse
(or variants, e.g. double.TryParse
)
TryParse
returns a bool
, where true
indicates successful parsing.
Remarks:
- Avoid int.Parse
if you do not know if the value parsed is definitely a number.
- Avoid Convert.ToInt32
entirely, this is an older method and Parse
should be preferred where you know the string can be parsed.
Read more hereint numbers = int.TryParse(Console.ReadLine(), out numbers);
?no, more like
for user input you'd probably want to put this in a loop that re-prompts the user if they type something that can't be parsed
and because that is annoying to do many times, its very cool to put it in a helper method
like
int number = AskUserForNumber("Enter your first number: ");
yeah, you can actually apply generics and delegates to this to make it very general purpose
and inside that method, you'd have the loop, the tryparse, etc
yep!
my own version of that method uses generics and delegates to handle validation, int vs double vs decimal etc
I'm a fan of just
but whatever works
Wow even this is confusing haha
So the
int.TryParse()
returns a bool.yes
what does the out do?
the out is one solution to basically return multiple things from a method
in this case if the text is parsed it will store the number in
numbers
which is a variable that you're declaring in-line inside the method callok so if the user type "2 3"
will that be stored?
it will fail because that's not a number
int.TryParse tries to turn the input text into a single number, if you want to parse multiple numbers you'll have to do some extra string processing first
it'll return false, and
numbers
will (at that point) exist but be 0, the default value, which is why you have to do the if check. So you can tell if they actually put in 0, or if it just couldn't read a valueSo i have to loop 2 numbers?
that's one solution, yeah
How am i supposed to store them under 2 different variable names
or rather, how can i apply the variable i?
either use a collection like a list or don't use a loop and just have 2 copies of your parsing code
Ah ok
I'll just have two copies of it
and if you want to still type the numbers on one line, you can have one ReadLine then
Split(' ')
the string into an array of multiple strings using the space as a delimiterSo how do i use the delegeate now?
I tried
calc.
but nothing about the delegate came up
Even tho the encaps is publicthe delegate itself is just a type, it describes the shape of a compatible method
you need a variable of that type to do anything with it
And i assume i can't create that inside main?
e.g.
CalculateAddOrSub<int> myDelegate = calc.Add;
sure you can
read that error closely
it does say what is wrong
woops typo
(and also check where you declared your
delegate
)lmfao i'm so confused i'm literally guessing my way through c# atm
remember, delegates are types, not members
Am i not supposed to create an instance of it?
of what?
CalculateAddOrSub
its a type, so you should declare a variable of that type
but look where its defined
??
I have literally no clue what i'm doing
what did we say about
T
and declaration vs usage?the variable can hold a method that matches the signature of the delegate, so you'd assign the method that you want to call later to the delegate
Ok so
you are quite close now
look at where
Add
is declared
and is it static or not?No it's not static
so why are you calling it as if it was?
I assume i need an instance of it then or make it static?
sure
Well i already have an instance of the class which holds the methods
right, so how would you access an instance method of a class?
calc.Add
exactly
But that uses the method directly, no?
And not utilize delegates
only if you call it with ()
without parentheses at the end it's just a reference to the method itself
CalculateAddOrSub<int> MyAddDelegate = calc.Add;
now you can call the delegate and it will indirectly call whatever method you've assigned here
I'm so confused lmfao
i don't even know what i'm trying to do anymore
so MyAddDelegate can be used like the name of a method
you can "call" the variable and it will call whatever method is stored in the variable
a more practical example here would be to ask the user what operation they want to do and store a different method in the delegate variable based on their answer
what do the errors say?
right
you've declared them inside the scope of the if statements, they don't exist outside those curly braces
but you don't need them, you already have val1 and val2
those are perfectly good variables
Ok it worked
That was horrible tho
Delegates are awful
they aren't, this exercise is just not a practical way to use them
Do you know any other exercise i could practice on?
Jimmacle
a more practical example here would be to ask the user what operation they want to do and store a different method in the delegate variable based on their answer
Quoted by
<@901546879530172498> from #Delegates. What are they and what are they used for? (click here)
React with โ to remove this embed.
also look into LINQ, that makes heavy use of delegates to give you very powerful ways to work with collections
the key takeaway here is that delegates allow you to write code that doesn't need to know exactly what methods it's calling to work
I'd like to but i simply don't have time, gotta prepare for exam
which lets you write much more generalized and flexible code
Is this what you meant?
By your practial example?
no
have one delegate variable, but assign it add or subtract based on the users input
Something like that?
closer
but not quite
your "call" should look like...
idk anymore
i'm just gpt
getting real close
you've set up the delegate
now you just need to call it
Ok so we set it to null since we dont know which method to use.
Then we assign which method to use in the switch case?
And now we call the method with val 1 and 2
?
yep
So to summarise, delegates are used if we dont know what method to call?
To me currently i dont see a point in using delegates.
I would've just called the add or sub function within the switch case from my instance of Calculate
Delegates seems very pointless
This is still the same kinda bad example of a use case as before
But imagine or maybe write it the other way around, where you first ask if they want to add or subtract. Then you call HandleInput(calc.Add) or (calc.Sub), and HandleInput is a method that asks for those numbers and just calls whatever method was passed to it
no, delegates are used so you don't have to know what method to call
you could write some method that accepts a
CalculateAddOrSub<int>
as an argument and that method can call it without actually knowing where the method comes from
like i said before, take a look at linq
you can't call something pointless if you don't want to look at proper use casesOfc i can :P seems pointless to me since in my example i could've just called the methods directly instead of using delegates
yes, in this specific example they aren't very useful
but you can still see how it allows calculating a
result
without knowing exactly what method is being used to do the calculationstimers are still probably a good example of when they are quite useful, if you wanted it to add those numbers 10s later, and you subtract them now, that timer has to be given a delegate so it knows what to do in 10s
But we do know?`It's the method we assign to the delegate?
but you've introduced a separation between the code that has to know and the code that doesn't
int result = MyDelegate(val1, val2)
doesn't know what MyDelegate will do, and it doesn't have towhen your programs get big and complicated, the 'you' that writes one method might be you from a month ago and not the same you that's writing the second method ๐ and so that second you doesn't know what the first one does anymore
:aaaa:
... yeah that probably didn't help lol, what I mean is it helps you be able to split things up and not have to think about all of it
you can write one method that just, asks for some numbers, and calls whatever method was given to it. And later, you (or someone else) can write the method that gets sent to it
No like i don't think i've been more confused in my life
it will make more sense when you get more C# experience
We wont get any more C# experience
it's a tool to abstract your code and make it more composable
final exam is next week
you can learn C# outside of school
often when we say things like "you don't know X", what we mean is that you should pretend you don't know X because X is handled somewhere else, it's not your job right now, and in theory someone else might be the one writing X, not you
๐ on my freetime?
i mean, yeah? if you want to
i learned pretty much all of what i know in my free time
is your goal to learn to program or just to pass a programming class?
I absolutely do not want to bring my schoolwork into my freetime ๐ญ
basically pretend that every method you write is a method someone else is going to call
I'm just looking to pass Uni
are you trying to get a job programming?
and that someone else would find it very convenient that they can just tell you what to do in your method (by passing you a method)
I have literally no idea what i want to do tbh
Medium to high income jobs are mainly provided after a degree
yes, but i'll tell you now that programming jobs require more knowledge and practice than uni will give you
so i just picked computer engineering program
Well yeah
and I'll recommend that if you don't like programming, don't do it as a job ๐
every single job requires experience
I enjoy programming. I don't enjoy not understanding
but maybe you'll start to like it, you're not really at the point where it's fun yet
if you spend more time learning you'll spend less time not understanding ๐
Easier said than done when the explanations to Delegates are 50 pages long
Especially having to learn it alone
there are 5 people in this thread helping you though
(which probably didn't make it easier :lul: )
Yeah i know, but delegates is a hard concept to learn
There really isn't a basic explanation for it
like i said, it will make more sense with more experience
there is
delegates are variables that hold methods instead of data
That i know
well, that's the basic explanation ๐
The problem is their utilization
Deferred execution. Define a method now, let someone else (or somewhere else) run it later
then we can come up with a better example, like the console prompting and parsing mentioned earlier
Oki
idk if @Pobiega wants to share one he has already or i'll just write a basic one quickly
oh i see a lot of usage of
=>
what does that do?it's a lambda, basically writing a method inline
so
x => x > 0
is a method that matches the delegate Func<T, bool>
here the delegate allows us to make Prompt check the input in the way that we need (making sure it's greater than 0)
but Prompt doesn't have to know that's exactly what we want to do
we can use the exact same method to get a number less than 0 just by changing the lambda to x => x < 0
hopefully that shows more how delegates can be useful to compose different behaviors together and let you make more reusable code
as another example, it can get only even numbers with x => x % 2 == 0
These are fields right, not properties?
those are properties
fields don't have get or set
hmm
guess i got them mixed up
Is lambda just essentially
=
but it iterates through a list?no, a lambda is another way to write a method (more or less)
it has nothing to do with iterating or lists
Huh
this code is functionally identical to the one i posted before
but using a "regular" method instead of a lambda
I explained them above if you need it worded a different way https://discordapp.com/channels/143867839282020352/1292841177971953674/1292859785363853395
In this example
They sort the list <People> for each person by the age?
Isn't that Lambda?
yes, this is an example of how you can use delegates with LINQ to do certain things more easily
OrderBy is a general purpose method that takes an argument of another method (using delegates) to select what to sort by
Person => Person.Age
is the lambda, but it doesn't do any iterating or sorting
all it does is accept a person as an argument and return that person's age
OrderBy does the rest of the workOk so lambda is built up on something called LINQ?
no
LINQ uses delegates, delegates can hold methods, lambdas are a way to write methods
LINQ is a collection of methods that you can use to work on collections like OrderBy, Select, Sum, etc.
they do a lot of the work for you and all you have to do is give them some extra information like what to order by, what to select, what to sum
and they do that by accepting methods that take in the type of object in the collection, doing something with it, and returning something else
like in your example, taking in a person and returning their age
you could do the same thing with a named method
if that helps
ok so lambda expressions are a way to pass anonymous methods?
exactly
a lambda is basically just a method with no name
funny enough, languages like JavaScript allow for self-invoking anonymous functions
eg.
In C# its a syntax error
arion
REPL Result: Failure
Exception: CompilationErrorException
Compile: 407.853ms | Execution: 0.000ms | React with โ to remove this embed.
Ok so lambda is an anonymous method
var sorterByAge = people.OrderBy(Person => Person.Age);
How does it work then?
We create a variable called sorterByAge as type var, and we assign it to be ...so that lambda
Person => Person.Age
becomes a Func<Person, int>
, which means its a method that takes a person in and returns an int
var
isnt a real type, its just "hey compiler, figure this out"OrderBy specifically returns an IOrderedEnumerable<T>
because the other thing about LINQ is that it doesn't actually evaluate anything until you try to iterate the enumerable
up until then you're basically building up a chain of operations without actually doing them
:harold:
it's not something you normally have to think about, but asking specifically how OrderBy works starts to get complicated
which is why i made the Prompt example of how delegates can be used in methods because it's much easier to understand
Func
is just a name, right?it's a delegate type
like in the base C# libraries there is a
public delegate TResult Func<T1, TResult>(T1 arg1);
(not exactly, but close enough)Like action, you can write up your own version too
I'm still a little clueless on delegates, lambda and <>
:(
imo generics are a rough topic for a new programmer