Sometimes the simplest questions make me love C/C++ and C# more and more.
Today sitting on the bus musing aout delegates I remembered
reading somwhere you don't need to use the new keyword when instaniating
a new delegate.
For example:
public static void SomeMethod(string message)
{
...
}
...
public delegate void TestDelgate(string message); //Define a delegate
...........
//create a new instance ..METHOD 1
TestDelgate t = new TestDelgate(SomeMethod);
//OR another way to create a new instance ..METHOD 2
TestDelgate t = SomeMethod; //create a new instance ..METHOD 2
So todays questions are
What happens under the hood in method 2. Does the compiler expand method 2 into method 1, hence writing TestDelgate t = SomeMethod; is just a shortcut for
TestDelgate t = new TestDelgate(SomeMethod);, or is there another reason for the exsitence of method 2
Do you guys think method 1 or method 2 is better for readability (this is a subjective question, but I'd just like to get a unscientific feel of general opinion of stackoverflow :-))
Yes, method 2 is just shorthand for method 1 - at least in the case of using a method group. You can also use:
TestDelegate t = new TestDelegate(someExistingDelegate);
which allows for variance (not just the generic variance from C# 4) and creates a separate delegate... but that's rarely useful.
Personally I go with option 2... method group conversions are very handy like that. In particular it makes event wiring simpler:
button.Click += LoadDocument;
instead of
button.Click += new EventHander(LoadDocument);
The latter just has extra fluff - the former has better information density. It's also important when you're passing the delegate as a method argument. For example, compare:
observable.Subscribe(new Action<string>(Console.WriteLine));
with
observable.Subscribe(Console.WriteLine);
Unless there's any ambiguity in terms of which delegate type you actually want to convert the method group to, I just use the implicit conversion.
Under-the-hood, your 2 methods are exactly the same. It is just the compiler being smart about what you want to do. This little feature is called delegate inference and was added in C#2.0.
I think you should use #2, and take advantage of delegate inference. They compile to the same IL, and option #2 is shorter and more concise. It is easier to read and understand the meaning of the code, because there is less noise.
This syntax is also supported for events.
It is sugar. The kind of sugar that really comes in handy when you have to write this:
someObj.Test -= new TestDelegate(SomeMethod);
What? You have to use the new keyword to remove an event handler. Yes, you do. The VB.NET team really pained about this, they decided for a completely different syntax:
RemoveHandler someObj.Test, AddressOf SomeMethod
Even the above C# statement is sugar, the real code looks like this:
someObj.Test.remove(new TestDelegate(this, SomeMethod));
Where "remove" is the accessor function for an event. And "this" is required to initialize the Delegate.Target property. Now it is obvious that it is actually a method call and using the new keyword suddenly makes sense again. Hiding "this" has some disadvantages too, it isn't obvious anymore that an event subscription will prevent an object from getting garbage collected.
Yes they are compiled into the same thing.
I prefer #2. Just because it is shorter and not so clumsy. You already know that it is a TestDelegate due to defining that before. So why write it again?
It's just syntatic sugar for the explicit delegate creation. This was introduced in C# 2.0. You may have noticed that Visual Studio 2008 still generates the old-style (method 1) syntax if you ask it to create an event handler; I always replace it manually by the new syntax.
I normally prefer the shorter form in method 2. I used method 1 only once: with a delegate that was to be invoked from native code, and therefore could not be garbage-collected. I wanted to be very explicit about creating and assigning it.
Under the hood both statements create delegate object and pass to parameters to ctor: address of method and reference to this. second is just syntax sugar.
One advantage of the 'new' syntax is that it informed the programmer that a new object was being allocated; if it would be desirable to avoid repeatedly creating new identical delegates, one could pull the delegate out to a field. I know that in fact one is allowed to use one delegate to subscribe and another to unsubscribe, but to me that feels wrong. Storing to a field the delegate used to subscribe, and then unsubscribing using that same delegate feels cleaner. Cleaner still, IMHO, would have been if the act of subscribing would have returned a MethodInvoker which, when called, would unsubscribe (in which case an "event" would simply be a function that accepted an EventHandler and returned a MethodInvoker), but that's not how .net events work.
Related
I have a button event declared like this :
myButton.Click += new EventHandler(ButtonClicked);
private void ButtonClicked(Object s, EventArgs e)
{
this.Close();
}
I can do exactly the same like this :
myButton.Click += (s, e) => this.Close();
I'm sure the advantage of using the second way of doing it is not just aesthetic.
Why and when should I use the second method because now I'm confused? If it's just for the look of it, it doesn't look much cleaner when you have more than one instructions in the body of your anonymous function.
Technically there is no difference. Compiler will generate handler method in second case.
But frankly speaking I almost never use anonymous event handlers. Why? because they do not have names. IDE can't help me to find place where event is handled. Do you remember exact place where you subscribed with anonymous method? Well, you possibly remember that place. But I bet your teammates don't.
Also I don't like mixing styles of event handlers. Visual Studio generates for me button1_Click methods. I don't like having some handlers subscribed this way, and some subscribed in place.
And I like to see event argument type. And yes unsubscribing also matters sometime. And few more points - anonymous methods are useful for very simple logic (like closing form in your case), but them become very messy with something more complex. And I think that putting event handler in place breaks single responsibility of your method. It subscribes to event, does some other stuff, and handles event in same place. I like to separate things in order to make them more readable and maintainable.
The compiler generates a method for this anonymous function (s, e) => this.Close(); either way,
It's up to you where you want to use it, declaring it inside a method will however let you access variables declared in that method.
Well you have essentially implictly applied a delegate to your Click event.
You can't access this event in code anywhere else. The main advantage to this is that you can't call your method any where else in your class, by having a method you are inviting other "Team Members" to access the method in their code or potentially change the modifiers of it to what they think should happen.
Should you want to be able to override a method, then obviously inline anonymous assignments are a dis-advantage.
The usage is more or less dependant on how you want to handle access to the logic.
You can do it even more elegant if you do not need the arguments:
myButton.Click += delegate { this.Close(); };
but there is no profit besides elegant look behind it.
I prefer NOT to use lambda expressions ( => ) if I don't really need them as you can't change the scope code during debugging.
Anonymous Functions can be anonymous methods or lambda expressions. The lamba expression is of the form:
() => //dowork
Anonymous Methods are more verbose and support remains mainly for backwards compatibility. Anonymous Functions do not have a value or type in and of themselves, but it is convertible to a delegate or expression tree. Anonymous functions allow us to create in-line methods which are useful in cases such as setting up an event handler. This in-lining of methods allows developers to write code "in the same place". In other words, the handler is immediately available to the reader at the location where the event is handled.
I strive to in-line methods when the implementation is limited to a few statements and not re-useable (as is often the case in event handlers). Lamba Expressions can also used extensively in the framework's extensions methods Enumerable.Select, Where etc. And in place of Action or Func when using the new parallels library or calling Control.Invoke.
Here is a similiar subject: delegate keyword vs. lambda notation that considers anonymous delegates and lambda expressions. Particurarly, the answer there is: Once it is compiled, there is no difference between them.
The first method is easier to support, to make more complex and to reuse.
Also it is not obvious how to unsubscribe the second method from the event
As long as you don't need the parameters, you can even use:
myButton.Click += delegate { this.Close(); };
which looks even cleaner.
But by using anonymous delegates comes the cost of code reusability, as others have pointed out. Also in the article How to: Subscribe to and Unsubscribe from Events. Microsoft states that:
It is important to notice that you cannot easily unsubscribe from an
event if you used an anonymous function to subscribe to it. To
unsubscribe in this scenario, it is necessary to go back to the code
where you subscribe to the event, store the anonymous method in a
delegate variable, and then add the delegate to the event. In general,
we recommend that you do not use anonymous functions to subscribe to events if you will have to unsubscribe from the event at some later
point in your code.
One of the strong points of the anonymous methods, which also separates them from lambda expressions, is that:
... There is one case in which an anonymous method provides
functionality not found in lambda expressions. Anonymous methods
enable you to omit the parameter list. This means that an anonymous
method can be converted to delegates with a variety of signatures.
This is not possible with lambda expressions.
As a conclusion for the paragraph above we can say that you can either pass no parameters at all, or you should pass in the exact signature of the event handler:
myButton.Click += delegate(object sender, EventArgs e) { this.Close(); };
A lot of time when creating simple events in my program that other classes can subscribe to instead of making a delegate and creating an event from the delegate I just create the event with either Action or Func to avoid having to create the delegate.
Is there any downsides to doing this?
Not really, the only downside I can think of is that if you have a logical intention (beyond the parameters and return values expected) that you want the user to satisfy that may get lost using the generic delegates.
For example:
public delegate void ClearAllValuesDelegate(MyClass X);
// ...
ClearAllValuesDelegate myDelegate;
vs:
Action<MyClass> myDelegate;
In the former, it's clear the intention is that the action should clear all the values in the reference (though there's no way to enforce this of course). Whereas Action<> just tells you what it takes and not much else. Like I said, this is just a logical difference.
But really there's no big downside that I'm aware of. Most of the time when we use Func<> and Action<> we are simply asking the caller to give us a target that satisfies the inputs/outputs only.
The main difference to me is the difference between:
And:
Obviously, there is at least some value in having the parameter named.
imho it's a matter of preference, to the CLR it's the same thing
Which one is better in, say, parameter type in a method (not related to LINQ).
Apparently Func is better since it's simpler, more descriptive, and if everyone is using this everything will become compatible (good).
However I notice Microsoft uses its own delegate at some libraries, for example event handlers. So, what are the advantages and drawbacks of either of them? when should I use it?
Edits:
Apparently Func<> was only available in 3.5, so this can possible be the main reason that I saw non-Func delegates. Any other reason to not use Func? (example: this is from .NET4)
The same question also applies for Action<>
Func<> is useful when it's very clear what they're used for, and the number of inputs is small.
When the number of inputs is larger, or there could be some ambiguity over the intent - then using a delegate with named arguments makes things clearer.
They are for all purposes the same, except when the method has an Expression parameter. Those need to be defined as a 'lambda' and not delegate. This would be very problematic when dealing with IQueryable and getting the IEnumerable invoked/resolved instead (eg LINQ2SQL).
Func<> and Action<> are preferable if they are actually appropriate in your case.
Runtime creates instances of every type used in your program, and if you use Func once it means that the instance of type was created. In case of custom delegate things go in different way and new types will be created even though they are essentially similar to existing.
However sometimes custom delegates make code clearer.
However I notice Microsoft uses its own delegate at some libraries, for example event handlers. So, what are the advantages and drawbacks of either of them? when should I use it?
Some of this is historic: APIs defined before C#3/.NET3 when Action<> and Func<> were added. For events EventHandler<T> is a better choice for events because it enforces the right convention.
You can always create a class which holds the n number of input as class properties and pass the object of the class a single input in the func<> delegate
I'm just looking at some of my code and it occurred to me that given,
Action<int> fireMessage = FireMessages;
fireMessage.BeginInvoke(1, r => fireMessage.EndInvoke(r), null);
As I can directly assign a method to a delegate, why can't I just call BeginInvoke on the method directly. The way this code reads suggests that the delegate assignment is redundant.
But calling BeginInvoke directly on the method throws up a compiler exception.
A method isn't a delegate - a delegate is distinct type which references a method - there is actually more information in a delegate than just the method.
Techically, it might be possible for the compiler to wire this up for you and shorten the typing, but I'm actually somewhat thankful that this wasn't done. By forcing you to assign a delegate to a method reference on an object, then invoke the delegate using BeginInvoke, the compiler is forcing you to be more explicit in your desire here.
Calling a delegate via BeginInvoke potentially has some serious side effects - this should be an explicit, purposeful action. Many methods will not behave as expected if they're called in separate threads, and at least this way, you need to know what you're doing in order to work in this manner.
That being said, in .NET 4, I'd recommend changing how you "fire methods" in "background threads". Instead of using Delegate.BeginInvoke, I'd recommend considering changing to using the new Task class:
Task.Factory.StartNew( () => FireMessages(1) );
There are many advantages to the new task library, especially when it comes to error handling, cancellation, prevention of oversubscription on the thread pool, etc.
There is a bit of syntactic sugar here. A delegate is really under the hood an object that wraps your method, and it happens to have the BeginInvoke method defined. The syntactic sugar is that you can assign a "method" to a delegate (without explicitly creating a delegate), but it only works in this context.
I think it is by design. In C# methods are not objects like they are in functional languages, but delegates are.
Delegate constructor is "point of touching" that is supported by C# compiler, and this is single place where method is used as 'method reference' instead of 'method invokation'.
Accessing 'instance's method instance' object using someInstance.Method.SomeMethodOfMethod have confusing syntax, and requires method instance. Some person may expect method instances obtained from the same method of the same object must be also same, and this will requires additional memory usage to store method instance inside object.
The compiler can automatically produce a delegate from a method group if it knows the type of delegate to produce. It cannot, however, infer the type of a delegate based upon a method group because different delegate types are in general not compatible, even if the signatures match. Although there are many situations where the compiler could in fact use any delegate with a particular signature, the compiler has no way of knowing what those situations are. Consequently, method groups are only converted implicitly to delegates in cases where the compiler can identify the delegate type via other means.
Can you tell me what the difference is between these methods of attaching an event handler?
//Method 1
this.button4.Click += new RoutedEventHandler(button4_Click);
//Method 2
this.button4.Click += button4_Click;
...
void button4_Click(object sender, RoutedEventArgs e) { }
As Anton says, there's no difference.
Just as a bit more background, this isn't specific to events. That's just one use of the feature in C# 2.0, which is implicit conversion of method groups to delegates. So you can similarly use it like this:
EventHandler handler = button4_click;
Another change to delegates in C# 2.0 is that they're now variant - this means that (for example) you can use a method declared with the EventHander signature as a MouseEventHandler:
MouseEventHandler handler = button4_click;
Then of course there's anonymous methods, but that's a whole different ballgame :)
No difference whatsoever - the second is just syntactic shugar added in C# 2.0. And in C# 3.0 lambdas are even more concise.
It is indeed syntactic sugar (it compiles to identical CIL)
The benefit to the first approach is that it is explict at the call site what event type you are using.
The benefit to the second is that, should the delegate type change but stay compatible the code will not require changing, if it changes but is incompatible you need only fix the method, not the places it is attached to the event.
As ever this is a balance as to which pro/con is more use to the situation at hand