Delegates, Actions, Events, Lambda expression and MVVM - c#

I have spent few days trying to understand WPF and MVVM. It is going very slowly mostly because I have some lack of knowledge in terms of events and stuff. Here bellow I will try to explain my understanding of all this things:
Method – this one is simple and I don't think it needs any explanation. Basic ingredient in any program.
Delegate – the way I see it is pointer on method. I can think of only few applications where I would want to use it over a method.
Action – that one is even trickier. Information I have managed to find say that it is a delegate that doesn't return value... so is it just pointer on void method? I don't see point of that
Event – this one I don't get at all. It was being explained with delegate and I didn't understand how does it work and what is it for. Note I was using events writing winforms applications but it was just choosing desired event from the list.
Event handler – even more unclear.
Lambda expression – also yet another way of using method. Again I understand it doesn't return anything, I can pass some argument in it, but still aint much different from void method. I have seen some applications like when using LINQ but I still don't understand how it works.
I would like to start by saying that I understand basic construct of MVVM, what is doing what and so on. Issue I have is that I don't understand some of the code, how does it work and therefore I can't write anything actually on my own. I will be using some tutorials as example so here it goes:
S1: https://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030
S2: http://social.technet.microsoft.com/wiki/contents/articles/18199.event-handling-in-an-mvvm-wpf-application.aspx
What I am expecting from you guys is some guidance or explanation how can I approach and understand those thinks to make them at least a little less scary for me. Here I will place some examples that will hopefully show you what kind of problems I have.
1) First one comes from S1 from well known RelayCommand class:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
I know what it is suppose to do (name speaks for itself). But I don't understand how this thing works? How it knows when to make something executable and when not. What are exactly those add and remove “commands”? I tried to read about it but it didn't help.
2) Another example form S1:
#region CloseCommand
/// <summary>
/// Returns the command that, when invoked, attempts
/// to remove this workspace from the user interface.
/// </summary>
public ICommand CloseCommand
{
get
{
if (_closeCommand == null)
_closeCommand = new RelayCommand(param => this.OnRequestClose());
return _closeCommand;
}
}
#endregion // CloseCommand
#region RequestClose [event]
/// <summary>
/// Raised when this workspace should be removed from the UI.
/// </summary>
public event EventHandler RequestClose;
void OnRequestClose()
{
EventHandler handler = this.RequestClose;
if (handler != null)
handler(this, EventArgs.Empty);
}
#endregion // RequestClose [event]
Again I know what it is suppose to do, I even understand what is basically happening here but I don't see where this “thing” is actually doing something. OnRequestClose() is just creating handler that in my eyes doesn't do anything to close whatever it is suppose to close. Problem is that if I even don't see where command is executed how can I write my own commands.
3) I think this will be last example, this time from S2:
public ViewModel()
{
_clickCommand = new DelegateCommand<string>(
(s) => { /* perform some action */ }, //Execute
(s) => { return !string.IsNullOrEmpty(_input); } //CanExecute
);
}
Here problem is pretty simple. It is creating command using RelayCommand ctor (or at least it's version in this project, here called “DelegateCommand”). I don't understand those (s) and use of lambda. What is it for?
Of course that isn't everything I have problem with but I think that will give idea what is my problem to anyone willing to help. I tried to explain my problem as best as I can and I would really appreciate any help or guidance. Maybe I am expecting to much from myself but I feel like I need to know all that stuff in order to write anything serious.
Anyway thank you all in advance for any help.

A long answer for your broad question.
Let me dig into Events and EventHandler first using a simple approach
Suppose there is a big function organized in your city which will host many famous people from your country.
Let's consider three guest's for this example
Guest one is a person who is unknown by other guests
Guest two is a famous person from your area and very few people know
Guest three is very famous across your country
Consider the following assumptions
Nobody is waiting for guest one (0 EventHandler)
There are four
people who are waiting for guest two (4 EventHandler's each person is
an event handler waiting to greet)
There are three security personnel and 10 guests (out of which one
person is also waiting for guest 2) waiting for guest 3 (13
EventHandler's)
Scenario 1
When guest one arrives at the venue (Event raised) nothing happens
Scenario 2
When guest two arrives at the venue (Event raised) the four people move towards him/her and give greetings
Scenario 3
When guest three arrives (Event) you will see security forces providing cover and ten people move towards him/her and give greetings
Simple points to be observed
1. Event is just a notification that something has happened (like a delegate with a method signature)
2. EventHandler is an action as to what happens when a specific event has happened ( a method which implements the method signature defined
by the delegate)
3. One event can have many eventhandlers (e.g.. scenario 2,3). Hence the syntax += in the below code sample
The below code will answer some of your basic questions
class Program
{
static void Main(string[] args)
{
var test = new Example();
Console.ReadLine();
}
}
class Example
{
//This is the event definition
delegate void ActionDelegate(string input1, string input2);
// Two event handler which implements the signature of the event
void ActionMethod(string a, string b)
{
Console.WriteLine(a + " " + b);
}
void ActionMethod2(string c, string d)
{
Console.WriteLine("Wow one more function called with parameter {0} and {1}", c, d);
}
delegate Tuple<string, string> LamdaDelegate(string input1, string input2);
public Example()
{
//Did not declare any delegate member variable explicitly.
//Clean and easy to understand
Action<string, string> action = ActionMethod;
// Had to define the delegate with method signature explicitly before using it
ActionDelegate actionDelegate = ActionMethod;
actionDelegate += ActionMethod2; // Attaching more event handlers to the event
//The below lambda expression implicitly means that it will take two inputs each of type string
// and does not return anything.
//The type information is implicitly derived from the method signature of the delegate
actionDelegate += (a, b) => Console.WriteLine("Called using lambda expression");
//Below is a Lambda expression in which s and e each is of type string
//Since the return type of the delegate is Tuple<string,string> the same is returned by the expression
//Lambda expression is using a delegate without defining a delegate explicitly.
LamdaDelegate myTuple = (s, e) => { return Tuple.Create(s, e); };
//The above Lambda can be rewritten as
myTuple += delegate (string a, string b) { return Tuple.Create(a, b); };
//Invoking the event handlers. The event handlers are executed automatically when ever the event occurs
action("Hi", "called from action");
actionDelegate("Hi", "called using explicitly defined delegate");
}
}
Why should we use delegates?
In the above example you saw that the ActionMethod is used by two different delegates(read Event).
Without delegates the above example would be dirty and unreadable.
The above example also shows Action which simplifies the need to define delegates explicitly.
Now comming to Commands
In MVVM the traditional event is replaced by Command and the event parameters (read delegate method signature) is replaced by CommandParameter
In your 3rd question the DelegateCommand has a type parameter which is string. So the (s) you see is a variable which stores the input string sent from UI. Now it is upto you to decide if you want to use the input (s) or ignore it all together. In the CanExecute part you can see that even when the input (s) is passed it has ignored it and uses the other member variable _input.
The 2nd question an event RequestClose is defined which is attached an event handler in Figure 7 of the link. Also observe that in the same figure the MenuItem is bound to the CloseCommand in the ViewModel.
So now when you click on the MenuItem the CloseCommand is invoked and it then calls the function OnRequestClose. The first thing this function checks is that is there anyone interested(read listening) in the event RequestClose which the MainWindow is listening and hence calls the window.Close()
For more clarification please do let me know.
EDIT
The code example above was just for Action<T> and delegate.
In layman terms let me put it this way
If I want to do something based on some external action I would use Event . I will just define an event and wire it up to an EventHandler and just wait for the action to occur. (In the example above I don't know when will the guest arrive but whenever they do arrive the EventHandler will respond automatically)
On the other hand I will use delegate if I want to call single/multiple functions simultaneously based on some internal condition defined in the code. In the code example above you can see that I had to invoke the delegate manually.
Please ignore the Tuple as it is just a return value with no actual importance.
EDIT 2
The scenario (_) or (s) is similar. Both mean that you will get a parameter as an input but in the first scenario the developer is trying to say that this parameter will not be used or ignored while in the (s) they intend to use it
You can't use just () as this means that the lambda expression does not contain any input parameter which is wrong since the definition says that it will receive a string as an input.

1. Delegate
the way I see it is pointer on method
Correct. However since C# is strongly typed, you need to define, what parameters and return type must the method have. This is what delegates are.
I can think of only few applications where I would want to use it over
a method.
This is not about method vs deledate. When you need to pass method as a parameter, then the parameter is defined using delegate.
2. Action
Action is concrete type of delegate. While delegate can refer to any method, Action says, that it is parameterless method with return type void. Action<string> means that parameter is of type string. Action<string, int> means that the method's first parameter must be of type string and second of type int.
Another concrete example of delegate is Func delegate. Func<bool> means that the method does not have parameters and returns bool. Func<string, bool> means that there is one input parameter of type string and it returns bool.
EventHandler is just another delegate, that represents method with void return type and two input parameters: object and EventArgs
3. Event
just think about Button.Click event. The programmers at microsoft that worked on Button class had to provide a way how to notify your program, that button was clicked. So they defined an event and you can handle the event by providing a method that will execute when the event occurs. The method is called eventhandler.
4. EventHandler
is either used as common name for methods that are assinged to events or it is concrete delegate that defines input and output parameters or it is used as.
e.g: Button.Click += DoSomehing; Click is an event. Method DoSomething is and eventhandler. Is must return void and have two input parameters of type object and EventArgs, because when you look at the definition of click event, you can see concrete delegate type which is EventHandler (or RoutedEventHandler - just another delegate used in WPF in some events).
5. Lambda expression
is very simple. Lambda expression is just another syntax to write a method. Compiler translates lambdas to methods anyway. Lambdas are just syntactic sugar.
following method and lambda are equal
bool IsGreaterThan5(int number)
{
return number > 5;
}
var isGreaterThan5 = new Func<int, bool>(number => number > 5);
for example, if you have an array of integers, then you can use Where linq extention method to filter the array. Intelli sense tells you, that the parameter of Where method is Func<int, bool>. Therefore you need to pass method that takes one parameter of type int and returns bool.
int[] numbers = new []{ 1, 2, 3 4, 5, 6, 7 };
var filteredNumbers = numbers.Where(IsGreaterThan5); //method IsGreaterThan5 is defined in previus example
//just another syntax:
var filteredNumbers = numbers.Where(number => number > 5);
//just another syntax:
var filteredNumbers = numbers.Where(new Func<int, bool>(number => number > 5));
//just another syntax:
Func<int, bool> isGreaterThan5 = i => i > 5; //it does not matter how you name the input parameter
var filteredNumbers = numbers.Where(isGreaterThan5);

Related

Delegate Subtractive Assignment

In C#, delegate behave more like a list of function pointers, so that we can call a list of methods with the same method signature via a delegate.
After the initial assignment, we can add or subtract methods from a delegate using += (additive assignment) and -= (subtractive assignment).
Say, I have two methods.
public static void Method1(string message){
// ...
}
public static void Method2(string message){
// ...
}
Now, I declare a delegate type,
public delegate void Del(string message);
If I want to execute Method1, Method2 and again Method1 in order, I can create a delegate like this.
Del delList = Method1;
delList += Method2;
delList += Method1;
Then, later in the program, If I remove Method1 from it, which occurrence of Method1 is removed? Is there any rule governing that?
I believe that the better and more readable way is to create a new delegate and add methods you want excute in order, instead of changing an existing one. I'm just curious about how -= operator is implemented for C# delegates.
If the matching performed by -= doesn't remove the one you wanted, you can call GetInvocationList(), manipulate it how you want, and make a new delegate.
However, that's only possible when you have access to the delegate. For fields, which only have operator+= and operator-= (subscribe and unsubscribe) behaviors, you'd best avoid duplicates if you care about the order of the calls.
Actually, it would probably be best to avoid duplicates altogether.
To answer the question about the specific behavior (though I still maintain that relying on it is far too confusing), operator-= uses Delegate.Remove, which is documented as:
Removes the last occurrence of the invocation list of a delegate from the invocation list of another delegate.
(The documentation for the Delegate class itself says "Managed languages use the Combine and Remove methods to implement delegate operations. Examples include the AddHandler and RemoveHandler statements in Visual Basic and the += and -= operators on delegate types in C#.")

C# Benefit of Delegates [duplicate]

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.
I have a function:
public long GiveMeTwoTimesTwo()
{
return 2 * 2;
}
This function sucks. What if I want 3 * 3?
public long GiveMeThreeTimesThree()
{
return 3 * 3;
}
Too much typing. I'm lazy!
public long SquareOf(int n)
{
return n * n;
}
My SquareOf function doesn't care what n is. It will operate properly for any n passed in. It doesn't know exactly what number n is, but it does know that n is an integer. You can't pass "Haha not an integer" into SquareOf.
Here's another function:
public void DoSomethingRad()
{
int x = 4;
long y = SquareOf(x);
Console.WriteLine(y);
}
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?
public void DoSomethingRad(int numberToSquare)
{
long y = SquareOf(numberToSquare);
Console.WriteLine(y);
}
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 that DoSomethingRad cares about is that we can give it an integer (numberToSquare) and that it gives us a long (because we put its return value in y and y is a long).
public long CubeOf(int n)
{
return n * n * n;
}
public void DoSomethingLeet(int numberToSquare)
{
long y = CubeOf(numberToSquare);
Console.WriteLine(y);
}
See how similar DoSomethingLeet is to DoSomethingRad? 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 can DoSomethingLeet. 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:
public long Radlicious(int doSomethingToMe, Func<int, long> doSomething)
{
long y = doSomething(doSomethingToMe);
Console.WriteLine(y);
}
We can call this method by writing this:
Radlicious(77, SquareOf);
Func<int, long> is a special kind of delegate. It stores behavior that accepts integers and spits out longs. 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 a long back.
We don't have to give any parameters to SquareOf because Func<int, long> describes behavior, not data. Calling Radlicious(77, SquareOf) just gives Radlicious the general behavior of SquareOf ("I take a number and return its square"), not what SquareOf 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 ints could be perceived as just really boring behavior:
static int Nine()
{
return 9;
}
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 return 9.
So what? I don't know.
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.
A delegate is a pointer to a method. You can then use your delegate as a parameter of other methods.
here is a link to a simple tutorial.
The question I had was 'So, why would I want to do that?' You won't really 'get it' until you solve a programming problem with them.
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.
A delegate instance is a reference to a method. The reason they are useful is that you can create a delegate that is tied to a particular method on a particular instance of a type. The delegate instance allows you to invoke that method on that particular instance even if the object on which you will invoke the method has left your lexical scope.
The most common use for delegate instances like this is to support the concept of callbacks at the language level.
It simply references a method. They come in great use with working with cross threading.
Here is an example right out of my code.
//Start our advertisiment thread
rotator = new Thread(initRotate);
rotator.Priority = ThreadPriority.Lowest;
rotator.Start();
#region Ad Rotation
private delegate void ad();
private void initRotate()
{
ad ad = new ad(adHelper);
while (true)
{
this.Invoke(ad);
Thread.Sleep(30000);
}
}
private void adHelper()
{
List<string> tmp = Lobby.AdRotator.RotateAd();
picBanner.ImageLocation = #tmp[0].ToString();
picBanner.Tag = tmp[1].ToString();
}
#endregion
If you didnt use a delegate you wouldn't be able to crossthread and call the Lobby.AdRotator function.
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 most basic terms, a delegate is just a variable that contains (a reference to) a function. Delegates are useful because they allow you to pass a function around as a variable without any concern for "where" the function actually came from.
It's important to note, of course, that the function isn't being copied when it's being bundled up in a variable; it's just being bound by reference. For example:
class Foo
{
public string Bar
{
get;
set;
}
public void Baz()
{
Console.WriteLine(Bar);
}
}
Foo foo = new Foo();
Action someDelegate = foo.Baz;
// Produces "Hello, world".
foo.Bar = "Hello, world";
someDelegate();
In most simplest terms, the responsibility to execute a method is delegated to another object. Say the president of some nation dies and the president of USA is supposed to be present for the funeral with condolences message. If the president of USA is not able to go, he will delegate this responsibility to someone either the vice-president or the secretary of the state.
Same goes in code. A delegate is a type, it is an object which is capable of executing the method.
eg.
Class Person
{
public string GetPersonName(Person person)
{
return person.FirstName + person.LastName;
}
//Calling the method without the use of delegate
public void PrintName()
{
Console.WriteLine(GetPersonName(this));
}
//using delegate
//Declare delegate which matches the methods signature
public delegate string personNameDelegate(Person person);
public void PrintNameUsingDelegate()
{
//instantiate
personNameDelegate = new personNameDelegate(GetPersonName);
//invoke
personNameDelegate(this);
}
}
The GetPersonName method is called using the delegate object personNameDelegate.
Alternatively we can have the PrintNameUsingDelegate method to take a delegate as a parameter.
public void PrintNameUsingDelegate(personNameDelegate pnd, Person person)
{
pnd(person);
}
The advantage is if someone want to print the name as lastname_firstname, s/he just has to wrap that method in personNameDelegate and pass to this function. No further code change is required.
Delegates are specifically important in
Events
Asynchronous calls
LINQ (as lambda expressions)
If you were going to delegate a task to someone, the delegate would be the person who receives the work.
In programming, it's a reference to the block of code which actually knows how to do something. Often this is a pointer to the function or method which will handle some item.
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.

The usage of delegate

i saw that delegate is used for custom events. as far example
delegate string FuncRef(string Val);
FuncRef fValue = GetFieldName;
fValue("hello");
what i do here just declare delegate and assign a function name to delegate and call like fValue("hello"); whenever it is required.
instead of calling the GetFieldName() through delegate i can call it directly. so i just want to know why should i use delegate to call function where as we can call function directly....what is the advantage of calling any function through delegate.
so please tell me in what kind of scenario delegate usage is required except event handling. please guide me with sample code and simulate a situation where i need to call function through delegate except event handling. please show me some real life scenario where we have to call function through delegate.
The reason to use delegates instead of calling the function directly is the same reason you do
var taxRate = 0.15;
var taxAmount = income * taxRate;
instead of
var taxAmount = income * 0.15;
In other words: using a variable to hold a reference to a callable entity (a delegate is exactly that) allows you to write code that can change its behavior depending on the parameters passed to it (the value of the delagate we 're passing in). This means more flexible code.
For examples of code that uses delegates you can look at LINQ (of course), but there's also the "delegates 101" example which is relevant in any language: filtering a list.
delegate string FuncRef(string Val);
FuncRef fValue; // class member
if (condition1)
fValue = GetFieldName1;
else if (condition2)
fValue = GetFieldName2;
else
fValue = GetFieldName3;
// Another function
fValue("hello");
Microsoft's tutorial code on C# delegates presents another interesting use case. In their example, an object called Bookstore has a method ProcessPaperbackBooks which takes a book processing delegate and applies it to each item in the class.
The cool part is that then, if you need say, a method which collects all the ISBNs of all the books in the store, you don't need to change anything in the bookstore class, but only to define a function which acts on books and pass that into the ProcessPaperbackBooks method. Delegated goodness will occur, and your new function will be applied to every item in the bookstore. Snazzy, no?
http://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx
Basically any place where you want to be able to specify at runtime which function should be called.
The async BeginInvoke/EndInvoke pattern is a perfect example of this; the callback is specified via a delegate.
Shortly: You can use delegates and events members in combination to be able for example to assign an event handler to a class which does not know it before, the button class knows when it has to trigger the click event and does not know yet, internally, you will bind mybutton_Click handler to it.
Linq to objects makes extensive use of delegates:
myAnimals.Where(animal => animal.CanSwim)
the parameter supplied to the Where method ( animal => animal.CanSwim ) is a lambda expression that converts to a delegate that is applied to all elements in myAnimals.
One place I use delegates is my input handler (C#, XNA)
I have a public void OnKeyboardPress() delegate, which I bind to various functions when certain keys are pressed.
Input is a good example; rather than polling for it (i.e. every update you go 'is it ready yet?' you wait for it to call you)..such as a GUI. WPF events are delegates.
Delegates are 1st class objects. IOW you can refer to them, reassign them, etc, just like any other object.

Creating two delegate instances to the same anonymous method are not equal

Consider the following example code:
static void Main(string[] args)
{
bool same = CreateDelegate(1) == CreateDelegate(1);
}
private static Action CreateDelegate(int x)
{
return delegate { int z = x; };
}
You would imagine that the two delegate instances would compare to be equal, just as they would when using the good old named method approach (new Action(MyMethod)). They do not compare to be equal because the .NET Framework provides a hidden closure instance per delegate instance. Since those two delegate instances each have their Target properties set to their individual hidden instance, they do not compare. One possible solution is for the generated IL for an anonymous method to store the current instance (this pointer) in the target of the delegate. This will allow the delegates to compare correctly, and also helps from a debugger standpoint since you will see your class being the target, instead of a hidden class.
You can read more about this issue in the bug I submitted to Microsoft. The bug report also gives an example of why we are using this functionality, and why we feel it should be changed. If you feel this to be an issue as well, please help support it by providing rating and validation.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=489518
Can you see any possible reason why the functionality should not be changed? Do you feel this was the best course of action to get the issue resolved, or do you recommend that I should take a different route?
I'm not so inclined to think this is a "bug". It appears moreover that you're assuming some behaviour in the CLR that simply does not exist.
The important thing to understand here is that you are returning a new anonymous method (and initialising a new closure class) each time you call the CreateDelegate method. It seems that you are experting the delegate keyword to use some sort of pool for anonymous methods internally. The CLR certainly does not do this. A delegate to the anonymous method (as with a lambda expression) is created in memory each time you call the method, and since the equality operator does of course compare references in this situation, it is the expected result to return false.
Although your suggested behaviour may have some benefits in certain contexts, it would probably be quite complicated to implement, and would more likely lead to unpredictable scenarios. I think the current behaviour of generating a new anonymous method and delegate on each call is the right one, and I suspect this is the feedback you will get on Microsoft Connect as well.
If you are quite insistent on having the behaviour you described in your question, there is always the option of memoizing your CreateDelegate function, which would insure that the same delegate is returned each time for the same parameters. Indeed, because this is so easy to implement, it is probably one of the several reasons why Microsoft did not consider implementing it in the CLR.
EDIT: Old answer left for historical value below the line...
The CLR would have to work out the cases in which the hidden classes could be considered equal, taking into account anything that could be done with the captured variables.
In this particular case, the captured variable (x) isn't changed either within the delegate or in the capturing context - but I'd rather the language didn't require this sort of complexity of analysis. The more complicated the language is, the harder it is to understand. It would have to distinguish between this case and the one below, where the captured variable's value is changed on each invocation - there, it makes a great deal of difference which delegate you call; they are in no way equal.
I think it's entirely sensible that this already-complex situation (closures are frequently misunderstood) doesn't try to be too "clever" and work out potential equality.
IMO, you should definitely take a different route. These are conceptually independent instances of Action. Faking it by coercing the delegate targets is a horrible hack IMO.
The problem is that you're capturing the value of x in a generated class. The two x variables are independent, so they're unequal delegates. Here's an example demonstrating the independence:
using System;
class Test
{
static void Main(string[] args)
{
Action first = CreateDelegate(1);
Action second = CreateDelegate(1);
first();
first();
first();
first();
second();
second();
}
private static Action CreateDelegate(int x)
{
return delegate
{
Console.WriteLine(x);
x++;
};
}
}
Output:
1
2
3
4
1
2
EDIT: To look at it another way, your original program was the equivalent of:
using System;
class Test
{
static void Main(string[] args)
{
bool same = CreateDelegate(1) == CreateDelegate(1);
}
private static Action CreateDelegate(int x)
{
return new NestedClass(x).ActionMethod;
}
private class Nested
{
private int x;
internal Nested(int x)
{
this.x = x;
}
internal ActionMethod()
{
int z = x;
}
}
}
As you can tell, two separate instances of Nested will be created, and they will be the targets for the two delegates. They are unequal, so the delegates are unequal too.
I don't know about the C# specific details of this problem but I worked on the VB.Net equivalent feature which has the same behavior.
The bottom line is this behavior is "By Design" for the following reasons
The first is that in this scenario a closure is unavoidable. You have used a piece of local data within an anonymous method and hence a closure is necessary to capture the state. Every call to this method must create a new closure for a number of reasons. Therefore each delegate will point to an instance method on that closure.
Under the hood a anonymous method / expression is represented by a System.MulticastDelegate derived instance in code. If you look at the Equals method of this class you will notice 2 important details
It is sealed so there is no way for a derived delegate to change the equals behavior
Part of the Equals method does a reference comparison on the objects
This makes it impossible for 2 lambda expressions which are attached to different closures to compare as equals.
I can't think of a situation where I've ever needed to do that. If I need to compare delegates I always use named delegates, otherwise something like this would be possible:
MyObject.MyEvent += delegate { return x + y; };
MyObject.MyEvent -= delegate { return x + y; };
This example isn't great for demonstrating the issue, but I would imagine that there could be a situation where allowing this could break existing code that was designed with the expectation that this is not allowed.
I'm sure there are internal implementation details that also make this a bad idea, but I don't know exactly how anonymous methods are implemented internally.
This behaviour makes sense because otherwise anonymous methods would get mixed up (if they had the same name, given the same body).
You could change your code to this:
static void Main(){
bool same = CreateDelegate(1) == CreateDelegate(1);
}
static Action<int> action = (x) => { int z = x; };
private static Action<int> CreateDelegate(int x){
return action;
}
Or, preferably, since that's a bad way to use it (plus you were comparing the result, and Action doesn't have a return value ... use Func<...> if you want to return a value):
static void Main(){
var action1 = action;
var action2 = action;
bool same = action1 == action2; // TRUE, of course
}
static Action<int> action = (x) => { int z = x; };

contravariance seem to cause a conflicted behavior

The following example is taken from C# in Depth: What you need to master C# 2 and 3, and seems to only only cause a breaking change as jskeet has identified, but be wrong. Please explain:
delegate void SampleDelegate(string x);
public void CandidateAction (string x)
{
Console.WriteLine("Snippet.CandidateAction")
}
public class Derived: Snippet
{
public void CandidateAction (object x)
{
Console.WriteLine("Derived.CandidateAction")
}
}
....
Derived x = new Derived();
SampleDelegate factory = new SampleDelegate (x.CandidateAction);
factory ("test");
Now, why should it work altogether as SampleDelegate accept string not the object. And to my knowledge, object doesn't derive from the string. It is the other way around. That's what contravariance permits under c# 2.0. The seems to demonstrate the opposite effect.
Conceptually, Derived.CandidateAction's signature is saying, "I can handle any object you want to throw at me." SampleDelegate's contract is "You have to be able to handle a string." Now if a method can handle any object, it can certainly handle a string. So Derived.CandidateAction is capable of fulfilling what SampleDelegate needs, and can therefore be assigned to a SampleDelegate variable.
I wrote a more detailed discussion of this (admittedly from a C# 4 point of view) at http://hestia.typepad.com/flatlander/2008/12/c-covariance-and-contravariance-by-example.html.
Contravariance allows you to use a method which has parameters which are a base type of the parameters in the delegate method signature.
The delegate signature defines what types will be passed to the method. The method itself can have types that are less "specific". In your example, when the delegate is invoked as string is being passed. It is perfectly ok for the actual method to only want an object because a variable of type object is allowed to hold an instance of type string.
This is most useful in event handling scenarios where you can write an event handler like this that can be attached to almost any event (even when the args parameter being passed is more specific like ItemCheckedEventArgs):
public void GenericHandler(object source, EventArgs args) {
//do something generic
}

Categories