use - C# (.Net Framework 4.5, Visual Studio 2012)
I try to understand such theme like Delegate, and currently I have few points, that must be clarified for me. I found a lot of different information in internet that describe how to use it, but it's a little bit complicated to understanding for me this theme.
As I understand I must to do few thing for using delegate:
- Create some entity for work with it (that require creating some delegate)
- Declare a delegate type
- Create some method where I call to delegate
- In main class call delegate with required method that use entity (from first point)
all described I show below
The question - am I correctly understand all or maybe I'm wrong - please clarify it.
Also another question regarding DELEGATE - where is better to put code with DELEGATE - in Console C# application I can create it in any place of used Namespace - as I can show below.
But maybe there is some recommendation/requirements for placing delegate not only for Console application but also for WinForms, WPF etc.
This theme is new for me and I spend a day for understanding it, but still a little bit (or a more) confused with this, finally create this post for better and clear understanding. think it's very powerfull stuff.
EDIT
namespace SimpleCSharpApp
{
delegate void myDelagate ();
}
Delegate declarations can be placed in any source file with public and internal accessibility. I personally place them at the top of a class source for which it is most applicable.
For instance if I have a specialized event delegate that takes CustomEventArgs as a parameter, I will put the delegate declaration at the top of that file:
Another option is to put delegates together in a single source file ... I haven't seen this done and would be subject to coding guidelines.
A delegate generally has two qualifications:
The first qualification is the declaration of a delegate:
... or using
Func<TResult>
orAction
:Since an event handler (declared delegate) generally does not have a return type (
void
), aFunc<TResult>
would not be used. A Func delegate requires a return type:See the linked MSDN articles for more on
Func<TResult>
andAction
. I only included references to these for completeness and insight on newer declaration methods.Func<TResult>
andAction
are specialized wrappers for thedelegate
.The second qualification for a delegate is a reference to a method or class member. I may have a private method that acts as a handler for specific needs. Say a FileIO object needs a specific file handler for different types of files - that is, .XML, .TXT, .CSV:
Now any object can implement it's own
OpenFile
definition based on the file type but must return aStream
object.By using both a delegate declaration and an interface, we can pass the
XMLHandler
object as anIFileHandler
and only expose the delegate via theFileHandler
property without exposing the entire object. Note that the method referenced by the delegate is private. This is a special benefit of the delegate (and Func, Action).Ho-ho.. you've got something messed up. I didn't quite grasp what problem you are trying to state until I saw the screenshot from VS with red underline under "delegate" declaration.
First, forget about the
public void delegate zczcxxzc
line for a moment. It is somewhat special. First, let's see some standard kinds *) of delegates.The two most basic ones are:
System.Action
System.Func
Both are generic and looking at their signature for the first time, they may seem overly complex. But, they are really very simple.
For starters, let's limit to bare, parameterless,
System.Action
.Just like "int" holds a number, "string" - text, a "delegate" holds information about "something callable", or, to use some terminology, "something invokable".
First, I create a delegate of type "Action" that remembers "myFunction1". Then I invoke/call that delegate - it results in the remembered function being called.
Then, I create a delegate of type "Action" that remembers "myFunction2". Then I invoke/call that delegate - it results in the remembered function being called.
Finally, I create a delegate of type "Action" that remembers "myFunction3". Then I invoke/call that delegate - it results in the remembered function being called, and nothing happens - but only because the target function did nothing.
Please note that I deliberately say "created a delegate". Each time a
new Action
is executed, a new delegate is created. A "delegate" is just an object, like String "foo" or float[] {1.2, 4.5}.Also, note that the full syntax for creating delegates used here is
new Action(...)
. Just like creating any object - new + typename + construction parameters. Yet another sign that a "delegate" is just an object.Another thing to note is that I did not write
new Action( myFunction1() )
. I did not want to CALL the method and get its result and give that result to the constructor of Action. I wrotenew Action( myFunction1 )
. I gave the function itself to the constructor.But, then, what is an "Action"? System.Action is a class. Like String, or Socket or WebClient. Nothing special here. So, we have a "class" whose objects can remember what-function-should-be-called. Cool.
Therefore some compare delegates to "function pointers". But that's not fully right. Function pointers can remember what function to call. Delegates can remember what method to call. Remember the difference? In my example above, I deliberately wrote
static
at eachmyFunction
. Those can be called object-less/target-less. You just need their name and you can call them from anywhere. To call them, a simple dumb pointer would be enough.Now, delegates can do more. They can work on methods. But methods need to be invoked against an object..
Ok, making a delegate to a static function in other class was easy - just had to say exactly what-function-from-what-class. Again just like calling, but without parenthesis.
But, if you try uncommenting the references to non-static methods, it will not compile. Looking at the
GuineaPig.Well
- that's obvious. It's not static, it needs to be called against OBJECT, not CLASS. For that very same reason, the delegate could not be created. Let's fix that:Note how classname was replaced with objectvariable during the creation of the delegate. The syntax is preserved: just like calling, but without parens. But, what's all the fuss about "methods" vs "functions"..
Delegates can store not only 'what method' to be called, but also what object to call them upon.
Now that is something you cannot do with plain function pointers. (Although with very smart function pointers you could.. but, let's leave that).
Note how the fact that "Well" was to be called on "pig#2" was stored inside the delegate object. The "myPiggie2" variable was irrelevant. I could nullify it. The delegate remembered both target and method.
System.Action is just one of the family. It's the simpliest, no params, no returns.. But there are many of them, they can get parameters (
Action<string, int>
) they can return values (Func<int>
) or both (Func<string,int>
). Yet, constantly speaking in terms ofFunc<int,float,string,int,int,bool,decimal>
is somewhat ... obscure.Ok. Let's finally get to the point of all this babbling. Sorry if you knew all of that, but I wanted to be clear.
A "delegate" is all about remembering "target" and "method". In fact, if you ever inspect a delegate in the debugger (or check what Intellisense says after the "dot"), you will see two properties, Target and Method. They are just what their names stand for.
Let's imagine you want to create your own type of a delegate. A type that would not be called
Func<int,int,int,bool,bool,Zonk,string>
, but rather, "MyStudentFilteringDelegate".Now, whole point is, that in C# you cannot take
&
(address) of a function easily, and also you cannot overload the operator(). This results in you being unable to write your own delegate-like classes.You cannot just write:
because, even if you actually managed to follow that idea, somewhere at the end you would find that:
At least, in current C# version 4.5 or 5.
You just cannot overload the "call"/"invoke" operator, hence you would not be able to fully implement your own, custom-named, delegate type. You'd be stuck at Actions and Funcs for ever.
Now recall that red underline under the
public void delegate xxx
I asked you to temporarily forget.This line does not create any delegate. This line defines a type of a delegate. It is perfectly the same as
Func<Student,bool>
, with custom name. *)In fact, the compiler converts the line to:
so that it is a class, and so that you can now create a delegate object:
As the class is special, compiler-generated, it can break rules. It's 'call'/'invoke' operator is overloaded, so you can "call" the delegate as it were a method.
Please note that despite the strange notation:
the
MyStudentFilteringDelegate
is a class, just like Action or Func or String or WebClient are. Thedelegate
keyword is just a marker for the compiler to know what transformation it should apply to that line to generate a proper "delegate type" (class).Now, to actually answer your other question:
It is really irrelevant where you put the delegate type declaration. You may write
public void delegate XYZ(...)
anywhere you like. Just as you may place a class declaration just about anywhere.You may place class declarations at default(no-namespace) scope, at some namespace, or inside a class. So, as the delegate-type is just a class, you may also delcare new delegate types at default(no-namespace) scope, at some namespace, or inside a class:
Note that I completely deliberately named them identically. That's no error. First are named
::global.Xc
and::global.Xd
, the second pair is namedWTF.Xc
andWTF.Xd
and the final pair is namedWTF.Whatever.Xc
andWTF.Whatever.Xd
. Just like normal clases.To decide where to place those declarations, use the same rules as you use for classes. Ie. if you place text-processing classes in namespace
MyApp.Text.Parsing
, then all the delegatetypes related to that text-processing should sit in that namespace too. But, even so, that's purely cosmetical and organizational. Place/define them at whatever scope it makes sense for you.EDIT: *) actually, historically, it was all other way around. The
delegate
keyword and compiler trick is older than the Action and Func classes. At .Net 2.0, the Action/Func did not exist. The only way to create/use a delegate was to define your own new delegate type (or find/guess some suitable one somewhere deep in the system's namespaces). Keep in mind that every new delegate-type is a new class. Not convertible to any other class, not even similarly-looking. It was so frustratingly tiresome and hard to mantain, that at .Net 3.5 they finally included "general purpose generic delegate types" in the framework. From that point of time, Action/Func are increasingly often used, because even if they are harder to read, they are .. universal.System.Func<Student,bool>
can be passed "anywhere", and you don't have a problem that 'bool delegate StudentFilter()from one library does not match
bool delegate StudentSelector()` from anoother one.Delegates in c# are a little bit like a replacement for function pointers in C++. There are plenty of usages for them. You can use them to:
From my experience the first usage is the most common.
Which can be simplified by a lamba expression:
You provide some behavior to a button click not having to create a separate method for it.
Regarding to the second part of your question, I usually put delegates declarations in separate files.