Using anonymous event in function - c#

public static void OnAutoScrollToEndChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
{
/* ... */
var scrollToEndHandler = new NotifyCollectionChangedEventHandler((sender, args) => // ́ˆ˜́ •
{
if (listBox.Items.Count > 0)
{
object lastItem = listBox.Items[listBox.Items.Count - 1];
listBoxItems.MoveCurrentTo(lastItem);
listBox.ScrollIntoView(lastItem);
}
});
if (isAutoScroll)
{
source.CollectionChanged += scrollToEndHandler; // A
}
else
{
source.CollectionChanged -= scrollToEndHandler; //B
}
}
https://michlg.wordpress.com/2010/01/17/listbox-automatically-scroll-to-bottom/
This code is referenced by upper URL.
A(scrollToEndHandler) and B(scrollToEndHandler) are in a function.
When 'AutoScrollToEndProperty' is changed, 'OnAutoScrollToEndChanged' will be called all the time.
I wondering whether These are same reference. Thanks.

If your question is basically, "Does unsubscription actually work here?" the answer is C# compiler implementation-specific, theoretically.
On a practical basis, the body of the lambda expression doesn't capture any local variables, but does capture this (by referring to listBox)... so I'd expect the compiler to generate an instance method containing the body of the code in the lambda expression.
If the method is called multiple times on the same target (i.e. this refers to the same object), I'd expect scrollToEndHandler to be a distinct but equal delegate each time - in other words, it would create a new delegate object in each call (which it probably wouldn't if the lambda expression didn't capture anything, and could be implemented as a static method and the delegate cached)... but the event subscription/unsubscription will still work because the delegates are equal (referring to the same target for the same method).
If the lambda expression referred to any local variables in the method, then event handling wouldn't work, because the compiler would capture those local variables via a separate nested class containing the relevant variables and a method for the delegate code, and each method invocation of OnAutoScrollToEndChanged would create a new instance of that nested class, leading to unequal delegates.
As I say though, that's all implementation-specific... it would be better to just move that code into a separate instance method, to make it clearer that it would work.

Related

Passing Actions into generic functions

I'm trying to wrap my head around different concepts in Csharp by trying different things. A create a generic function that takes in an action. The action has one input parameter and returns void. I create a simple action that is linked to a lambda function (returns void has one parameter x). I am able to run the action but when I pass the function to my generic function I am not sure how to add the input parameter. act("Some Int") doesn't work.
How do I pass in a value to an action?
public MainWindow()
{
InitializeComponent();
Action<int> myAction = (x) => Console.WriteLine(x);
myAction(13);
test(myAction);
}
private static void test<T>(Action<T> act)
{
act(); // How do i pass in an int Here?
}
Simply calling act("Some Int") as you have just required the Action act to be a genric function. Therefore you cannot specifically invoke it with one fixed variable type. You can solve your problem by modifying the test-method
private static void test<T>(Action<T> act, T value)
{
act(value); // How do i pass in an int Here?
}
...
test(myAction,integerValue);
Now you can call the Action with a given intvalue.
I can see what you are trying to do, and just wanted to throw this pattern up, since we often do this when we have to use closures and the parameters could be wildly different.
In those cases, rather than define an Action<T> which kind of ties you down from being able to use closures, you would just simply define your method as Action. So test would look like this:
private static void test(Action act)
{
act(); // yup, that's all there is to it!
}
So how would you pass in the parameter(s)? Simple: use closures. Like this:
public MainWindow()
{
InitializeComponent();
var x = 13; // this defined outside now...
Action myAction = () => Console.WriteLine(x); // you're basically using the closure here.
myAction();
test(myAction);
}
We often use this sort of approach when we're context switching (aka thread jumping), and need the thread continuation to pick up one or more variable values at the point it executes. That's just one example, there's quite a few other valid use cases as well.
Your experimental example, if I'm reading it correctly, could also qualify as a situation where closures could be a good fit.

Subscribing to events using anonymous methods

I am having problems understanding how the below works (questions below code):
private delegate void MyDelegate(int i);
private event MyDelegate myEvent;
public void EventTests() {
//Option One
myEvent += One;
//Option Two
myEvent += delegate{ Two(true); };
//Option Three
myEvent += () => { Two(true); };
}
private void One(int i) { }
private void Two(bool j) { }
Questions:
I can understand why Option One works, as the event myEvent expects a delegate with an int parameter to be attached to it. Why does Option Two work though? it is attaching an anonymous method with incorrect signature to the event, no?
So if Option Two works, why does option Three not work? It seems that the signature needs to be (int i) => { Two(true); }; as opposed to () as written above. But Option Two worked without the right signature, so why does this anonymous method cause an error?
Thanks a lot.
Option two works because the compiler automatically figures out what the function signature is when the parameter list is omitted. Once you add the () to the delegate keyword, you've defined a specific parameter list of none and the compiler throws a fit.
Option three is a lambda expression with an incorrect parameter list defined.
Microsoft's C# Programming Guide states:
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.

How do I change the name of an existing event handler?

In Windows Forms, if you change the method name (for example, button1_Click) to something else, it doesn't work any more.
I find this strange because in a console application, as far as I remember, you could name the methods as you wished. I'm trying to understanding what's happening.
How can I change the name of these methods (such as button1_Click)?
This questions is about the case where renaming a method causes the forms designer to stop working. Although I have covered (all that I can think of) how events works in general.
What happened?
What you experience is an artifact of the forms designer.
Sure, you can have any method name you want, the matter is the forms designer is binding those methods to events behind the scenes, if you change the method name after the forms designer has linked it to the event it will no longer work (it can't find the method).
Giving proper names to your event handlers
In Visual Studio, look at the properties of the object you want to bind an event to, and then select events (on the top of the panel):
There you will see a list the available events and you will be able to bind an existing method or type the name for a new one:
If I have already screwed, how do I fix it?
If your designer is not appearing because of this you will have to edit the code file that is generated by the designer. The file generated by the designer has the name of the form followed by .Designer.cs (for example: Form1.Designer.cs), you can find it with your solution explorer:
Note: You may have to expand the sub-tree created on your form to reveal the file.
There you will find a line that looks something like this:
this.button1.Click += new System.EventHandler(this.button1_Click);
And Visual Studio will tell you that button1_Click is not defined. You can edit there the name of the method to the new name, or remove the line to have the designer work again, and bind a new method.
Renaming an existing method without the hassle
You can summon the Rename dialog. This can be done by several ways:
From the Menus: Edit -> Refactor -> Rename
By contextual Menu on the name of the Method: Refactor -> Rename
Put the cursor on the Method name and type Alt + Shift + F10 and then select Rename
Put the cursor on the Method name and press F2
Note: You can customise your Visual Studio, the above menus and keyboard shortcuts may be changed.
The Rename dialog looks like this:
There you can type a new name for the method, and by doing so any reference or call to that method withing the loaded projects will be changed too. That includes the code generated by the Forms Designer.
Binding an event handler by hand
All that the forms designer does is present a UI that facilitates editing the form and write code on your behalf. Don't let it fool you into thinking that you can't write code yourself.
In fact, you can create your own methods and even bind them to the events of your Form. I have been saying "bind" because it is easier to understand at this level, although the accepted lingo is subscribe. So what we are going to do, is create a button and subscribe to its Click event.
First let's take a look at the class of your form, it looks something like this:
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
Notice it says partial, that means that there could be more code for this class in another file, in fact that is the file Form1.Designer.cs where the forms designer has been adding code.
Second notice it calls a method InitializeComponent inside the constructor of the form. This method has been created by the forms designer and it takes responsibility of initializing all the controls and components you have added using the forms designer (hence the name of the method).
Now, let's say we want to add a button without the forms designer we can do it like this:
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Button myButton;
public Form1()
{
InitializeComponent();
// Create a new Button
myButton = new Button();
// Set the properties of the Button
myButton.Location = new System.Drawing.Point(50, 12);
myButton.Size = new System.Drawing.Size(100, 23);
myButton.Text = "My Button";
// Add the Button to the form
this.Controls.Add(myButton);
}
}
}
We have created a private field named myButton of type Button that will hold the new button. Then inside the constructor we add some new lines to create a new Button and assign it to myButton and give it position (Location), Size and Text. And finally we have added the newly created button to the Controls of the form.
Now we want to add an event handler for the Click event on this new button. Remember that this button is not in the forms designer, we we are going to have to do it "by hand".
In order to do so, add the new method (you can named whatever you want):
private void WhenClick(object sender, System.EventArgs e)
{
/* Code */
}
And then add it as an event handler for the Click event of the button (inside the constructor):
// Add an event handler
myButton.Click += new System.EventHandler(WhenClick);
Notice we are not calling WhenClick. instead we are making a reference to it.
Then we are creating a new Delegate of type System.EventHandler that will wrap the reference to the method WhenClick. I suggest to learn about Using Delegates.
I repeat: we are not calling WhenClick. If we were to call WhenClick we would do something like this: WhenClick(param1, param2). Please note that this is not what we are doing here, we haven't added parenthesis (/*...*/) after the method name, so we are not doing a method call.
You can also use some syntactic sugar to make all this easier:
public Form1()
{
InitializeComponent();
// Create a new Button and set its properties
myButton = new Button()
{
Location = new System.Drawing.Point(50, 12),
Size = new System.Drawing.Size(100, 23),
Text = "My Button"
};
// Add the Button to the form
this.Controls.Add(myButton);
// Add an event handler (the compiler infers the delegate type)
myButton.Click += WhenClick;
}
You can even make the event handler an anonymous method:
// Add an event handler (the compiler infers the delegate type)
myButton.Click += (sender, e) =>
{
/* code */
};
What you see here is a C# Lambda expression (more info at MSDN Lambda expressions). Get used to these syntax, because you will see them more and more often.
Understanding events
You have already seen code like this:
button1.Click += button1_Click;
As I told you we are passing a delegate object that has a reference to button1_Click. But that's not all that happens here... we are also giving it to Click.
Let's recapitulate and see how delegates behave. You can think about a delegate like an object that holds a method, or a pointer to a function if you prefer.
To understand this, I'll present some examples you can run as console applications. The first one shows that you can change the method that a delegate points to during runtime:
// Console Application Example #1 ;)
static void Main()
{
Func<int, int> myfunc = null;
myfunc = Add2;
Console.WriteLine(myfunc(7)); // This prints 9
myfunc = MultBy2;
Console.WriteLine(myfunc(7)); // This prints 14
}
static int Add2(int x)
{
// This method adds 2 to its input
return x + 2;
}
static int MultBy2(int x)
{
// This method multiplies its input by 2
return x * 2;
}
Notice myfunc is typed as Func<int, int> this is a generic delegate type that takes an int and returns an int.
Also notice that when I say myfunc = Add2;, it is not calling Add2 (there are no parenthesis there), it is passing a reference of the method itself. the same is true for myfunc = MultBy2;: it is not calling MultBy2, we are passing it.
Using anonymous methods via lambda expressions you can write equivalent code is less lines:
// Console Application Example #1 ;)
static void Main()
{
Func<int, int> myfunc = null;
// This anonymous method adds 2 to its input
myfunc = x => x + 2;
Console.WriteLine(myfunc(7)); // This prints 9
// This anonymous method multiplies its input by 2
myfunc = x => x * 2;
Console.WriteLine(myfunc(7)); // This prints 14
}
Notice that we have two anonymous methods here: x => x + 2 and x => x * 2. The first one (x => x + 2) is equivalent to the method Add2 we had before, and the second one (x => x * 2) is equivalent to the method MultBy2 we had before.
In this example I want you to see that the same delegate can point to different methods along the time. This is accomplished by having a variable that points to the methods!
For the second example, I'll present the "callback" pattern. That is a common pattern in which you pass a delegate as a "callback", that is: something that will be called "back to you" from the code you are calling:
// Console Application Example #2 ;)
static void Main()
{
Func<int, bool> filter = IsPair;
// An array with numbers
var array = new int[]{1, 2, 3, 4, 5, 8, 9, 11, 45, 99};
PrintFiltered(array, filter);
}
static bool IsPair(int x)
{
// True for pair numbers
return x % 2 == 0;
}
static void PrintFiltered(int[] array, Func<int, bool> filter)
{
if (array == null) throw new ArgumentNullException("array");
if (filter== null) throw new ArgumentNullException("filter");
foreach (var item in array)
{
if (filter(item))
{
Console.WriteLine(item);
}
}
}
Outputs:
2
4
8
In this code we are having a variable filter that points to the method IsPair. I'll repeat this again and and again: in the line Func<int, bool> filter = IsPair; we are not calling the method IsPair, instead we are taking a reference to it.
Of course, it is possible to do the same without declaring the filter variable, you can pass the method reference directly:
// Console Application Example #2 ;)
static void Main()
{
// An array with numbers
var array = new int[]{1, 2, 3, 4, 5, 8, 9, 11, 45, 99};
PrintFiltered(array, IsPair); //<---
}
static bool IsPair(int x)
{
// True for pair numbers
return x % 2 == 0;
}
static void PrintFiltered(int[] array, Func<int, bool> filter)
{
if (array == null) throw new ArgumentNullException("array");
if (filter== null) throw new ArgumentNullException("filter");
foreach (var item in array)
{
if (filter(item))
{
Console.WriteLine(item);
}
}
}
I cannot stress this hard enough: When I say PrintFiltered(array, IsPair); it is not calling IsPair, it is passing it as a parameter to PrintFiltered. Here effectively you have a method (PrintFiltered) that can take a reference to another method (IsPair) as a reference.
Of course you can write the same code using an anonymous method that replaces IsPair:
// Console Application Example #2 ;)
static void Main()
{
// An array with numbers
var array = new int[]{1, 2, 3, 4, 5, 8, 9, 11, 45, 99};
PrintFiltered(array, x => x % 2 == 0);
}
static void PrintFiltered(int[] array, Func<int, bool> filter)
{
if (array == null) throw new ArgumentNullException("array");
if (filter== null) throw new ArgumentNullException("filter");
foreach (var item in array)
{
if (filter(item))
{
Console.WriteLine(item);
}
}
}
Outputs:
2
4
8
In this example x => x % 2 == 0 is an anonymous method that is equivalent to the method IsPair we had before.
We have successfully filtered the array to only show the numbers that are pair. You can easily reuse the same code for a different filter. For example, the following line can be used to output only the items in the array that are less than 10:
PrintFiltered(array, x => x < 10);
Outputs:
1
2
3
4
7
8
9
With this example I want to show you that you can take advantage of the delegates to improve the reusability of your code, by having parts that change depending on the delegate you pass.
Now that - hopefully - we understand this, it is not hard to think that you could have a list of Delegate objects, and call them in succession:
// Console Application Example #3 ;)
static void Main()
{
// List<Action<int>> is a List that stores objects of Type Action<int>
// Action<int> is a Delegate that represents methods that
// takes an int but does not return (example: void func(int val){/*code*/})
var myDelegates = new List<Action<int>>();
// We add delegates to the list
myDelegates.Add(x => Console.WriteLine(x));
myDelegates.Add(x => Console.WriteLine(x + 5));
// And we call them in succesion
foreach (var item in myDelegates)
{
item(74);
}
}
Outputs:
74
79
You can see both anonymous methods (x => Console.WriteLine(x) and Console.WriteLine(x + 5)) has been called, one after the other... this happens inside the foreach loop.
Now, we can accomplish similar results with a multicast delegate:
// Console Application Example #3 ;)
static void Main()
{
// This is a delegate... we haven't give it a method to point to:
Action<int> myDelegates = null;
// We add methods to it
myDelegates += x => Console.WriteLine(x);
myDelegates += x => Console.WriteLine(x + 5);
// And we call them in succession
if (myDelegates != null) // Will be null if we don't add methods
{
myDelegates(74);
}
}
Outputs:
74
79
Again, both anonymous methods has been called. And this is exactly how events work. The default implementation of an event uses a multicast delegated wrapped inside. Custom implementation of an event may use a list or similar structure to hold the delegates.
Now, if the event is just a list of delegates... that means the event is keeping a reference to all the methods it wants to call. And it also means that you could remove delegates from the list (or add more than one).
If you want to unsubscribe or unbind from an event, you can do so like this:
this.button1.Click -= button1_Click;
For a delegate object to an anonymous method it is a little bit more complicated, because you will need to keep the delegate in a variable to able to pass it back for removal:
Action<int> myDelegates = null;
// Create the delegate
var myDelegate = x => Console.WriteLine(x);
// Add the delegate
myDelegates += myDelegate;
// ...
// Remove the delegate
myDelegates -= myDelegate;
Did you say custom implementation of an event?
Does that means you can create your own events? Yes, and yes. If you want to publish an event in one of your classes you can declare it just like any other member.
This is an example that uses a multicast delegate:
// Event declaration:
public event EventHandler MyEvent;
// Method to raise the event (aka event dispatcher):
priavet void Raise_MyEvent()
{
var myEvent = MyEvent;
if (myEvent != null)
{
var e = new EventArgs();
myEvent(this, e);
}
}
For a custom implementation take this example:
// List to hold the event handlers:
List<EventHandler> myEventHandlers = new List<EventHandler>();
// Event declaration:
event EventHandler MyEvent
{
add
{
lock (myEventHandlers)
{
myEventHandlers.Add(value);
}
}
remove
{
lock (myEventHandlers)
{
myEventHandlers.Remove(value);
}
}
}
// Method to raise the event (aka event dispatcher):
private void Raise_MyEvent()
{
var e = new EventArgs();
foreach (var item in myEventHandlers)
{
item(this, e);
}
}
Hopefully this not hard to read, now that you know how events work. The only details should be lock, it is there because List is not thread-safe. You could also use a thread-safe data structure or a different locking mechanism, I kept this one for simplicity.
Even if you don't write your own events, there are a few things to learn from here:
Event handlers execute consecutively (by default), so it is good idea that event handlers execute fast (maybe defer to asynchronous operations for the hard work) to prevent "clogging" the event dispatcher.
The event dispatcher usually don't handle exceptions (it can be done), so it is good idea to avoid throwing excepting in event handlers.
The "publisher" of the event is keeping a list of the event handlers, it is a good idea to unsubscribe when you don't need need the event handler anymore.
Notes:
While looking for example I found the series of articles "Delegates in C# - Attempt to Look Inside" by Ed Guzman (Part 1, Part 2, Part 3 and Part 4) very easy to read - although a bit outdated - you should check them out. You may want to read the Evolution of Anonymous Functions in C# for a grasp of what's missing.
Some commonly used Delegate Types built-in in .NET include:
Generic
Action<*> (that is: Action<T>, Action<T1, T2> ...)
Func<*, TResult> (that is: Func<T, TResult>, Func<T1, T2, TResult> ...)
EventHandler<TEventArgs>
Comparison<T>
Converter<TInput, TOutput>
Non Generic
Action
Predicate
EventHandler
ThreadStart
ParametrizedThreadStart
You may be interested in LINQ.
Threading and thread-safety it a even broader topic than delegates and events, don't rush to understand it all.
If you want play along with Lambda Expression and C# in general, I suggest to get a copy of LINQPad. This make reduce the hassle of creating new project to test things.
You can of course change the name of your event. It just sounds like you don't know about the designer file :)
The designer file is just the result of your UI design, and if you don't update the name of your event in the UI it does not compile :)

How does a delegate remember it's parameters? [duplicate]

This question already has answers here:
The scope of variable in inner anonymous method
(2 answers)
Closed 9 years ago.
Consider this code:
public ModelView(Model model) : this()
{
Loaded += (object sender, RoutedEventArgs e) =>
{
DataContext = model;
};
}
When the Loaded event runs again, the parameter model is present in memory, however it was never explicitly saved, was it?
When you create an anonymous method or a lambda, the compiler creates a new class behind the scenes, with some internal name like <ModelView>ctor_0 or something similar. This class has a method, which is the contents of your lambda, but it also has properties with capture the local state of function where the lambda is defined, and make it available to the lambda.
See the Variable Scope in Lambda Expressions section in the Lambda Expression documentation on MSDN:
The following rules apply to variable scope in lambda expressions:
A variable that is captured will not be garbage-collected until the delegate that references it becomes eligible for garbage collection.
Variables introduced within a lambda expression are not visible in the outer method.
A lambda expression cannot directly capture a ref or out parameter from an enclosing method.
A return statement in a lambda expression does not cause the enclosing method to return.
A lambda expression cannot contain a goto statement, break statement, or continue statement that is inside the lambda function if the jump statement’s target is outside the block. It is also an error to have a jump statement outside the lambda function block if the target is inside the block.
In addition to #Avner's answer, this is what the C# compiler (sort of) generated for you under the covers:
public ModelView(Model model) : this()
{
var closure = new AnonymousClass { _this = this, model = model };
Loaded += closure.Loaded;
}
private class AnonymousClass
{
public ModelView _this;
public Model model;
public void Loaded(object sender, RoutedEventArgs e)
{
_this.DataContext = model;
}
}

Multicast delegate weird behavior in C#?

I have this simple event :
public class ClassA
{
public event Func<string, int> Ev;
public int Do(string l)
{
return Ev(l);
}
}
And 2 Methods :
static int Display(string k)
{
return k.Length;
}
static int Display_2(string k)
{
return k.Length*10;
}
Im registering this event :
ClassA a = new ClassA();
a.Ev += Display;
a.Ev += Display_2;
Now , I'm executing :
Console.WriteLine(a.Do("aaa"));
the output :
What ???
he has in invocation list 2 methods ! it did run them , but why does it shows only the result from the last registration ?
Where does the result of "3" has gone ? ( the first invocation ) ? ( although both display+display_2 was executed... I didn't expect console.write to iterate through results . but also didn't expect him to decide which to show.)
edit :
There are three aspects at play here:
The implementation of the event
The behaviour of delegate combination
The behaviour of invoking a delegate whose invocation list has multiple entries
For point 1, you have a field-like event. Section 10.8.1 of the C# 4 spec gives an example, and states that:
Outside the declaration of the Button class, the Click member can be used only on the left-hand saide of the += and -= operators, as in
b.Click += new EventHandler(...);
which appends a delegate to the invocation list of the Click event
(emphasis mine). The spec also makes it clear that a field-like event creates a delegate field, which is used from within the class for invocation.
More generally (point 2), section 7.8.4 of the C# 4 spec talks about delegate combination via + and +=:
Delegate combination. Every delegate type implicitly provides the following predefined operator, where D is the delegate type:
D operator +(D x, D y)
The binary + operato performs delegate combination when both operands are of some delegate type D. [... skip bits where x or y are null ...] Otherwise, the result of the operation is a new delegate that, when invoked, invokes the first operand and then invokes the second operand.
(Again, emphasis mine.)
Finally, point 3 - event invocation and return values. Section 15.4 of the C# spec states:
If the delegate invocation includes output parameters or a return value, their final value will come from the invocation of the last delegate in the list.
More generally, it depends on the event implementation. If you use an event implementation which uses the "normal" delegate combination/removal steps, everything is guaranteed. If you start writing a custom implementation which does crazy things, that's a different matter.
As a general rule, it doesn't make sense for events to return a value.
If you want to get information from an event handler it makes more sense for the event handlers to mutate an input parameter, or just call another method of whatever object fired the event to communicate something else.
Normally this doesn't even come up because events logically are passing information to the event handlers, and don't have any need to get information from the event handlers. It's honestly a sign of code smell. An event shouldn't care if anyone has subscribed to it, who they might be, what they might be doing, or even if there are any subscribers. Relying on a return value from them then just creates overly tight coupling.
Invoking a multicast non-void delegate returns the value of the last handler that was executed.
You have very little control over who is first or last. It is a lousy system to use.
That is why most events and delegates return void.
The events are just iterated in the order they were attached. Because you are using a return value, the value you get is the last invoked.
This is not really a normal pattern for events though. You probably want something a bit more like:
public class MyEventArgs : EventArgs
{
public MyEventArgs()
{
Results = new List<int>();
}
public string InputString{get;set;}
public List<int> Results{get;set;}
}
public event EventHandler<MyEventArgs> Ev
public int Do(string l)
{
MyEventArgs e = new MyEventArgs();
e.InputString = l;
if(Ev != null) Ev(this, e);
return e.Results.Sum();
}
and then
static int Display(object sender, MyEventArgs e)
{
return e.Results.Add(k.Length);
}
static int Display_2(object sender, MyEventArgs e)
{
return e.Results.Add(k.Length*10);
}

Categories