Get the lambda to reference itself - c#

I am trying to make lambda able to reference to itself, an example:
PictureBox pictureBox=...;
Request(() => {
if (Form1.StaticImage==null)
Request(thislambda); //What to change to the 'thislambda' variable?
else
pictureBox.Image=Form1.StaticImage; //When there's image, then just set it and quit requesting it again
});
When I tried to put the lambda in variable, while the lambda referenced to itself, error of course.
I thought about creating class with a method that able to call itself, but I want to stick here with lambda. (While it gives only readibility so far and no advandges)

You need to declare the delegate, initialize it to something so that you are not accessing an uninitialized variable, and then initialize it with your lambda.
Action action = null;
action = () => DoSomethingWithAction(action);
Probably the most common usage I see is when an event handler needs to remove itself from the event when fired:
EventHandler handler = null;
handler = (s, args) =>
{
DoStuff();
something.SomeEvent -= handler;
};
something.SomeEvent += handler;

As of C# 7, you can also use local functions:
PictureBox pictureBox=...;
void DoRequest() {
if (Form1.StaticImage == null)
Request(DoRequest);
else
pictureBox.Image = Form1.StaticImage; //When there's image, then just set it and quit requesting it again
}
Request(DoRequest);

Here is an interesting post on the subject from the experts -
http://blogs.msdn.com/b/wesdyer/archive/2007/02/02/anonymous-recursion-in-c.aspx
Excerpt from the post -
"A quick workaround is to assign the value null to fib and then assign the lambda to fib. This causes fib to be definitely assigned before it is used.
Func<int, int> fib = null;
fib = n => n > 1 ? fib(n - 1) + fib(n - 2) : n;
Console.WriteLine(fib(6)); // displays 8
But our C# workaround doesn't really use recursion. Recursion requires that a function calls itself."
Read the entire post, if you are looking for other fun ways of doing it.

Related

How can I extract the "real" target from an Event Handler that was defined anonymously?

Follow up to my question here:
According to a comment made -
The compiler creates a class member with a fictitious name and attaches it just as you would attach a declared method.
I do not fully comprehend what this means but I can verify that if instead of saying
Foo.Bar += (S, E) => { /*Code Goes Here*/ }
I instead say
Foo.Bar += FooBar;
private void FooBar( object sender, EventArgs e ){
/*Code Goes Here*/
}
then Event.Target changes from WhatIsThis.App.<>c to WhatIsThis.App.
That's awesome but I can't guarantee that I will always write an actual method to attach to an event handler.
In the cases where I do use an anonymous method, is there a way to extract the real target, or am I just pigeonholed into using defined methods (I mean, I can live with that I guess but if there's some high-tech sorcery that I can employ to extract the real target, then I'm all for it ).
do not fully comprehend what this means
Let's fix your comprehension. Suppose you have:
class C
{
int x;
void M(int y)
{
int z = GetZ();
Func<int, int> f = q => q + x + y + z;
...
f is a delegate. It has a receiver and a method that is a method of the receiver. (Note, this is not actually a strict requirement but the corner case is obscure for our purposes today.)
What type is the receiver that has that method?
Can it be C, with the receiver equal to this? No. Why not? Because then how do we keep track of the value of y and z? There could be a different value for every invocation of M, so the receiver cannot be this.
What the compiler does is generates a new class:
class C
{
int x;
class Locals
{
public C __this;
public int y;
public int z;
public int A(int q) { return q + __this.x + y + z; }
}
void M(int y)
{
Locals locals = new Locals();
locals.__this = this;
locals.y = y;
locals.z = GetZ();
Func<int, int> f = locals.A;
...
So what is the receiver? the value of locals. What is the method? A.
Of course both Locals and A are given crazy names so that you cannot call them by accident.
In the cases where I do use an anonymous method, is there a way to extract the real target
You are extracting the real receiver, I promise.
'm working on an extension to do some things with Event Handlers and I need to be able to discern what an event handlers target is
Please don't do that. The receiver of an event handler is an implementation detail of the code that provided the handler. It's not there for you to make decisions on. Compilers are well within their rights to make any choice they like when generating a receiver for an event handler, and they do. Consider what happens if the event handler was created inside an iterator block, or an async method, for example. Or the event is being subscribed by some reactive extensions code that is applying sequence operations to the event. Again, the compiler will be generating classes all over the place. You can't rely on the class being something "sensible".
The thing you can rely on is: the subscriber wished the given method to be called when something happened. That's the contract you must obey; don't try to second-guess the subscriber.

Anonymous function and local variables

Say you have a button on your form. You attached an anonymous function to button's Click event:
void Test()
{
int x = 10;
btn.Click += (sender, e) => { MessageBox.Show(x.ToString()); };
}
This works as expected and displays 10; means it can access local variables. My question is how and why? How does an anonymous function get access to the local context?
The actual problem I'm dealing with is that I need to upgrade (so to speak) this anonymous function to a regular function (event handler). But doing that means I'll lose access to the variable x. I can't pass it in as a parameter too because then I'll not be able to attach it to Click event (signature mismatch). I can work around this by creating global variables and all that, but how do anonymous functions make it possible to access things that were outside their scope?
Half of the point of anonymous functions are that they can capture the context in which they're specified. It's extremely convenient to be able to do so - that's the "why" part.
The way the compiler does this is to create a new class in cases where it needs to. So your code would be converted to something like:
void Test()
{
TestHelper helper = new TestHelper();
helper.x = 10;
btn.Click += helper.Method;
}
private class TestHelper
{
public int x = 10;
public void Method(object sender, EventArgs e)
{
MessageBox.Show(x.ToString());
}
}
Every use of x within Test is converted into a use of helper.x for the appropriate instance. This is how variables with different lifetimes is covered too. For example, suppose you had a loop like this:
for (int i = 0; i < 10; i++)
{
int x = i;
// Use with some anonymous function
}
then it would create a new instance of TestHelper for each iteration of the loop... whereas if x had been declared outside the loop, there'd just be a single instance that all the anonymous functions would effectively share.
When it's just this that's captured, the compiler creates an instance method within the existing class instead of creating a helper class. When there are different scopes with potentially multiple anonymous functions which capture a variety of variables, things can get a lot more complicated, with some helper classes having references to instances of other helper classes, etc.

How do outer variables within a loop work with lambdas?

I just wrote some code that I don't quite comprehend how it works.
My question is about the local variables in the for loop which are then referenced when the radio button event occurs.
How does it track the different "versions" of these local variables and operate correctly? (i.e. the resulting radio buttons each fire an event with their corresponding value which is derived from an outer local variable)
public class RadioButtonPanel<T> : FlowLayoutPanel
{
public RadioButtonPanel()
{
foreach (object value in Enum.GetValues(typeof(T)))
{
string name = Enum.GetName(typeof(T), value);
var radioButton = new RadioButton { Text = name };
radioButton.CheckedChanged += (s, e) =>
{
if (radioButton.Checked && this.Selected != null)
Selected((T)Enum.Parse(typeof(T), name));
};
this.Controls.Add(radioButton);
}
}
public event SelectedEvent Selected;
public delegate void SelectedEvent(T t);
}
This is done via a Closure.
Basically you can imagine that a small class has been created for you on your behalf, that has two properties for your local variables, and a single function. When your lambda gets called, it basically news one of those up and calls the function, thus preserving the values given to it.
The C# specification actually has some really good examples of how this is done by the compiler. Specifically section 6.5.3
They're called closures, see Wikipedia: http://en.wikipedia.org/wiki/Closure_(computer_science)
Basically, they allow for the use of non-local variables within the lambdas. From what I can remember, these variables are compiled externally from your function so they can be used globally.

Pass an event as a parameter to a method [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to pass an event to a method?
Is it possible to pass an event as a parameter to a method?
For example, the following method subscribes to the event, does work, and unsubscribes from the event:
void SubscribeDoAndUnsubscribe<TElement, TEventArgs>(
IEnumerable<TElement> elements,
??? elementEvent)
where TEventArgs: EventArgs
{
EventHandler<TEventArgs> handler = (sender, e) => { /* Handle an event */ };
foreach (var element in elements)
{
// Subscribe somehow
element.elementEvent += handler
}
// Do things
foreach (var element in elements)
{
// Unsubscribe somehow
element.elementEvent -= handler
}
}
Client code:
var elements = new [] { new Button(), new Button() };
SubscribeDoAndUnsubscribe(elements, ??? /* e => e.Click */);
If it's not possible, how do I achieve the similar logic in other ways? Shall I pass pair of delegates for subscribe/unsubscribe methods?
You have in fact discovered that events are not "first class" in C#; you cannot pass around an event as data. You can pass around a delegate to a method associated with a receiver as a first-class object by making a delegate. You can pass around a reference to any variable as a (mostly) first-class object. (I say "mostly" because references to variables cannot be stored in fields, stored in arrays, and so on; they are highly restricted compared to other kinds of data.) You can pass around a type by obtaining its Type object and passing that around.
But there is no way to directly pass around as data an event, property, indexer, constructor or destructor associated with a particular instance. The best you can do is to make a delegate (or pair of delegates) out of a lambda, as you suggest. Or, obtain the reflection object associated with the event and pass that around, along with the instance.
No, unfortunately not.
If you look at Reactive Extensions, that suffers from a similar problem. Three options they use (IIRC - it's been a while since I've looked):
Pass in the corresponding EventInfo and call it with reflection
Pass in the name of the event (and the target if necessary) and call it with reflection
Pass in delegates for subscription and unsubscription
The call in the latter case would be something like:
SubscribeAndDoUnsubscribe(elements,
handler => e.Click += handler,
handler => e.Click -= handler);
and the declaration would be:
void SubscribeDoAndUnsubscribe<TElement, TEventArgs>(
IEnumerable<TElement> elements,
Action<EventHandler<TEventArgs>> subscription,
Action<EventHandler<TEventArgs>> unsubscription)
where TEventArgs: EventArgs
You're trying to get around type safety, and you can't do so without using reflection. I'll show you an even simpler example of what you're trying to do.
void DoSomethingOnSomethingElse(T obj, Action method)
{
obj.method();
}
C# doesn't work this way. How does the compiler know that all Ts have the method method? It doesn't, and can't. Similarly, not every TElement in your code will have an event Click for example.
It sounds like you just want to set a single use event handler on a set of objects. You can do this quite easily...
EventHandler handler = null;
handler = (s,e) =>
{
DoSomething(e);
var b = (Button) s;
b.Click -= handler;
}
foreach (var button in buttons)
{
button.Click += handler;
}
This, obviously, only works with buttons, but as I write this, I see Jon Skeet has shown you a more general solution, so I'll end here.

event driven methods and execution sequence in c#.NET

Hypothetically speaking, if I had two methods (event handlers) driven by the same event, which method is executed first?
Example:
obj.SomeEvent += new SomeEventHandler(method1);
obj.SomeEvent += new SomeEventHandler(method2);
Which is called first?
Thanks!
It's up to the event publisher, but usually it would be whichever handler was added to the event first. That's the default implementation for an event which is basically implemented using a delegate. So for example:
SomeDelegate eventHandlers = null;
eventHandlers += FirstHandler;
eventHandlers += SecondHandler;
eventHandlers(...);
That will definitely call FirstHandler before SecondHandler. However, there's no guarantee that an event will be implemented just using delegates like that.
EDIT: While the event handling behaviour is up to the event publisher, the delegate combination part is well-specified in the C# language specification, section 7.8.4:
[...] Otherwise, the result of the operation is a new delegate instance that, when invoked, invokes the first operand and then invokes the second operand.
The BCL Delegate.Combine method makes a similar guarantee (emphasis mine):
(Return value) A new delegate with an invocation list that concatenates the invocation lists of a and b in that order. Returns a if b is null, returns b if a is a null reference, and returns a null reference if both a and b are null references.
The first subscribed one. "First in - first served".
The default implementation will cause event handlers to be called in the order they were added, however, it is possible to customize this behaviour. If the behaviour is customized, the client cannot tell this. So the real answer to your question is that the order in which event handlers is raised "depends" and could even change at runtime, however, the vast majority of events have default implementation.
For example:
public class ReverseBling
{
private readonly List<EventHandler> _blings = new List<EventHandler>();
public event EventHandler Bling
{
add
{
_blings.Add(value);
}
remove
{
_blings.Remove(value);
}
}
public void RaiseBling()
{
for (int i = _blings.Count - 1; i >= 0; i--)
{
_blings[i](this, EventArgs.Empty);
}
}
}
private static void Main()
{
ReverseBling bling = new ReverseBling();
bling.Bling += delegate { Console.WriteLine(0);};
bling.Bling += delegate { Console.WriteLine(1); };
bling.Bling += delegate { Console.WriteLine(2); };
bling.RaiseBling();
}
Output:
2
1
0
There is no way of telling which event handler will be invoked first. Many people think the first one to subscribe will be invoked first (which is normally the case) but not specified by the CLI.

Categories

Resources