Can someone please break down what a delegate is into a simple, short and terse explanation that encompasses both the purpose and general benefits? I've tried to wrap my head around this and it's just not sinking in.
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
It simply references a method. They come in great use with working with cross threading.
Here is an example right out of my code.
If you didnt use a delegate you wouldn't be able to crossthread and call the Lobby.AdRotator function.
It's interesting that no-one has mentioned one of key benefits of delegation - it's preferable to sub-classing when you realise that inheritance is not a magic bullet and usually creates more problems than it solves. It is the basis of many design patterns, most notably the strategy pattern.
In the absolute most simplest terms I can come up with is this: A delegate will force the burdens of work into the hands of a class that pretty much knows what to do. Think of it as a kid that doesn't want to grow up to be like his big brother completely but still needs his guidance and orders. Instead of inheriting all the methods from his brother (ie subclassing), he just makes his brother do the work or The little brother does something that requires actions to be taken by the big brother. When you fall into the lines of Protocols, the big brother defines what is absolutely required, or he might give you flexibility to choose what you want to make him do in certain events (ie informal and formal protocols as outlined in Objective-C).
The absolute benefit of this concept is that you do not need to create a subclass. If you want something to fall in line, follow orders when an event happens, the delegate allows a developed class to hold it's hand and give orders if necessary.
I have a function:
This function sucks. What if I want 3 * 3?
Too much typing. I'm lazy!
My
SquareOf
function doesn't care whatn
is. It will operate properly for anyn
passed in. It doesn't know exactly what numbern
is, but it does know thatn
is an integer. You can't pass"Haha not an integer"
intoSquareOf
.Here's another function:
Contrary to its name, DoSomethingRad doesn't actually do anything rad. However, it does write the SquareOf(4) which is 16. Can we change it to be less boring?
DoSomethingRad
is clearly still pretty fail. But at least now we can pass in a number to square, so it won't write 16 every time. (It'll write 1, or 4, or 9, or 16, or... zzzz still kinda boring).It'd be nice if there was a way to change what happens to the number passed in. Maybe we don't want to square it; maybe we want to cube it, or subtract it from 69 (number chosen at random from my head).
On further inspection, it seems as though the only part of
SquareOf
thatDoSomethingRad
cares about is that we can give it an integer (numberToSquare
) and that it gives us along
(because we put its return value iny
andy
is along
).See how similar
DoSomethingLeet
is toDoSomethingRad
? If only there was a way to pass in behavior (DoX()
) instead of just data (int n
)...So now if we want to write a square of a number, we can
DoSomethingRad
and if we want to write the cube of a number, we canDoSomethingLeet
. So if we want to write the number subtracted from 69, do we have to make another method,DoSomethingCool
? No, because that takes too damn much typing (and more importantly, it hinders our ability to alter interesting behavior by changing only one aspect of our program).So we arrive at:
We can call this method by writing this:
Func<int, long>
is a special kind of delegate. It stores behavior that accepts integers and spits outlong
s. We're not sure what the method it points to is going to do with any given integer we pass; all we know is that, whatever happens, we are going to get along
back.We don't have to give any parameters to
SquareOf
becauseFunc<int, long>
describes behavior, not data. CallingRadlicious(77, SquareOf)
just gives Radlicious the general behavior ofSquareOf
("I take a number and return its square"), not whatSquareOf
will do to any specific integer.Now if you have understood what I am saying, then you have already one-upped me, for I myself don't really get this stuff.
* END ANSWER, BEGIN WANDERING IDIOCY *
I mean, it seems like
int
s could be perceived as just really boring behavior:That said, the line between what is data and behavior appears to blur, with what is normally perceived as data is simply boring-ass behavior.
Of course, one could imagine super "interesting" behavior, that takes all sorts of abstract parameters, but requires a ton of information to be able to call it. What if it required us to provide the source code that it would compile and run for us?
Well, then our abstraction seems to have gotten us all the way back to square one. We have behavior so abstract it requires the entire source code of our program to determine what it's going to do. This is fully indeterminate behavior: the function can do anything, but it has to be provided with everything to determine what it does. On the other hand, fully determinate behavior, such as
Nine()
, doesn't need any additional information, but can't do anything other than return9
.So what? I don't know.
Like others have said, a delegate is a reference to a function. One of the more beneficial uses(IMO) is events. When you register an event you register a function for the event to invoke, and delegates are perfect for this task.
In the simplest possible terms, it's essentially a pointer to a method.
You can have a variable that holds a delegate type (just like you would have an int variable that can hold an int type). You can execute the method that the delegate points to by simply calling your variable like a function.
This allows you to have variable functions just like you might have variable data. Your object can accept delegates from other objects and call them, without having to define all the possible functions itself.
This comes in very handy when you want an object to do things based on user specified criteria. For example, filtering a list based on a user-defined true/false expression. You can let the user specify the delegate function to use as a filter to evaluate each list item against.