472,331 Members | 1,493 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,331 software developers and data experts.

very strange effect with anonymous delegates (.net 2.0)

I have a very funny/strange effect here.

if I let the delegate do "return
prop.GetGetMethod().Invoke(info.AudioHeader, null);"
then I get wrong results, that is, a wrong method is called and I have no
clue why.
But if I store the MethodInfo in a local variable I works as expected.

I do not understand why this is so, shouldn't both ways be semantically
equal?

foreach (PropertyInfo prop in typeof(Au.AuHeader).GetProperties())
{
ColumnInfo col = ColumnInfoFromProperty(prop);

// very strange effect: If I do not store MethodInfo here in a local
variable,
// but instead call prop.GetGetMethod() directly from the delegate I get
wrong results
MethodInfo mi = prop.GetGetMethod();

col.SortValue = delegate(FileInformation info) { return
mi.Invoke(info.AudioHeader, null); };

cols.Add(col);
}
Nov 17 '05 #1
5 1595
"cody" <de********@gmx.de> wrote in message
news:ec**************@TK2MSFTNGP14.phx.gbl...
I have a very funny/strange effect here.

if I let the delegate do "return
prop.GetGetMethod().Invoke(info.AudioHeader, null);"
then I get wrong results, that is, a wrong method is called and I have no
clue why.
But if I store the MethodInfo in a local variable I works as expected.

I do not understand why this is so, shouldn't both ways be semantically
equal?

foreach (PropertyInfo prop in typeof(Au.AuHeader).GetProperties())
{
ColumnInfo col = ColumnInfoFromProperty(prop);

// very strange effect: If I do not store MethodInfo here in a local
variable,
// but instead call prop.GetGetMethod() directly from the delegate I
get wrong results
MethodInfo mi = prop.GetGetMethod();

col.SortValue = delegate(FileInformation info) { return
mi.Invoke(info.AudioHeader, null); };

cols.Add(col);
}


Ahh the wonders of anonymous delegates and closures.

Have you had a look at what the IL looks like for a method with an anonymous
delegate? You get a generated class and all data that is accessed from the
enclosing scope become members of that class.

In the first case prop becomes a member of the class in the second mi does.
Do you see the problem? prop changes on each iteration, therefore you end up
creating a delegate referring to the place where the iterator got to when
the delegete fired.

In the second, each mi is local to each iteration so the delegate gets the
correct property

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk
Nov 17 '05 #2
>>I have a very funny/strange effect here.

if I let the delegate do "return
prop.GetGetMethod().Invoke(info.AudioHeader, null);"
then I get wrong results, that is, a wrong method is called and I have no
clue why.
But if I store the MethodInfo in a local variable I works as expected.

I do not understand why this is so, shouldn't both ways be semantically
equal?

foreach (PropertyInfo prop in typeof(Au.AuHeader).GetProperties())
{
ColumnInfo col = ColumnInfoFromProperty(prop);

// very strange effect: If I do not store MethodInfo here in a local
variable,
// but instead call prop.GetGetMethod() directly from the delegate I
get wrong results
MethodInfo mi = prop.GetGetMethod();

col.SortValue = delegate(FileInformation info) { return
mi.Invoke(info.AudioHeader, null); };

cols.Add(col);
}


Ahh the wonders of anonymous delegates and closures.

Have you had a look at what the IL looks like for a method with an
anonymous delegate? You get a generated class and all data that is
accessed from the enclosing scope become members of that class.

In the first case prop becomes a member of the class in the second mi
does. Do you see the problem? prop changes on each iteration, therefore
you end up creating a delegate referring to the place where the iterator
got to when the delegete fired.

In the second, each mi is local to each iteration so the delegate gets the
correct property


Sorry, maybe Iam stupid, but I still do not see the difference.
Both mi and prop are local variables which are 'lifted' to a field, right
when
the delegate is created. So there shouldn't be any difference, should it?
Nov 17 '05 #3
"cody" <de********@gmx.de> wrote in message
news:OS**************@TK2MSFTNGP12.phx.gbl...
I have a very funny/strange effect here.

if I let the delegate do "return
prop.GetGetMethod().Invoke(info.AudioHeader, null);"
then I get wrong results, that is, a wrong method is called and I have
no clue why.
But if I store the MethodInfo in a local variable I works as expected.

I do not understand why this is so, shouldn't both ways be semantically
equal?

foreach (PropertyInfo prop in typeof(Au.AuHeader).GetProperties())
{
ColumnInfo col = ColumnInfoFromProperty(prop);

// very strange effect: If I do not store MethodInfo here in a local
variable,
// but instead call prop.GetGetMethod() directly from the delegate I
get wrong results
MethodInfo mi = prop.GetGetMethod();

col.SortValue = delegate(FileInformation info) { return
mi.Invoke(info.AudioHeader, null); };

cols.Add(col);
}


Ahh the wonders of anonymous delegates and closures.

Have you had a look at what the IL looks like for a method with an
anonymous delegate? You get a generated class and all data that is
accessed from the enclosing scope become members of that class.

In the first case prop becomes a member of the class in the second mi
does. Do you see the problem? prop changes on each iteration, therefore
you end up creating a delegate referring to the place where the iterator
got to when the delegete fired.

In the second, each mi is local to each iteration so the delegate gets
the correct property


Sorry, maybe Iam stupid, but I still do not see the difference.
Both mi and prop are local variables which are 'lifted' to a field, right
when
the delegate is created. So there shouldn't be any difference, should it?


But prop is changing every time around the loop, mi is local to the loop and
so is fixed for each iteration.

If you look at the generated code (e.g in reflector) you will see that in
the case of using the iterator, the generated class is instantiated once
outside of the loop as that is the scope of the iterator.

In the case of the local variable, the generated class is instantiated
inside the loop as that is the scope of mi.#

So for the iterator the single integer value ends up as the last iterated
one, for the local variable its each value is captured in a separate
instance.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Nov 17 '05 #4
Ok I had a look in reflector and I now see the problem. Since in generated
code there is no local variable "PropertyInfo prop" but instead just a call
to "enumerable.Current" so there is nothing to 'lift'.

This maybe right from the view of the ILCode but it is toally wrong from the
view of the sourcecode since "PropertyInfo prop" is a readonly variable from
the programmer's view.

Iam the opinion that is is a very dangerous pitfall. If MS won't fix that,
they should at least throw a compiler error when a foreach iterator is used
in a anonymous method.

What do you think about that?

"Richard Blewett [DevelopMentor]" <richard at nospam dotnetconsult dot co
dot uk> schrieb im Newsbeitrag news:ez**************@TK2MSFTNGP10.phx.gbl...
"cody" <de********@gmx.de> wrote in message
news:OS**************@TK2MSFTNGP12.phx.gbl...
I have a very funny/strange effect here.

if I let the delegate do "return
prop.GetGetMethod().Invoke(info.AudioHeader, null);"
then I get wrong results, that is, a wrong method is called and I have
no clue why.
But if I store the MethodInfo in a local variable I works as expected.

I do not understand why this is so, shouldn't both ways be semantically
equal?

foreach (PropertyInfo prop in typeof(Au.AuHeader).GetProperties())
{
ColumnInfo col = ColumnInfoFromProperty(prop);

// very strange effect: If I do not store MethodInfo here in a local
variable,
// but instead call prop.GetGetMethod() directly from the delegate I
get wrong results
MethodInfo mi = prop.GetGetMethod();

col.SortValue = delegate(FileInformation info) { return
mi.Invoke(info.AudioHeader, null); };

cols.Add(col);
}

Ahh the wonders of anonymous delegates and closures.

Have you had a look at what the IL looks like for a method with an
anonymous delegate? You get a generated class and all data that is
accessed from the enclosing scope become members of that class.

In the first case prop becomes a member of the class in the second mi
does. Do you see the problem? prop changes on each iteration, therefore
you end up creating a delegate referring to the place where the iterator
got to when the delegete fired.

In the second, each mi is local to each iteration so the delegate gets
the correct property


Sorry, maybe Iam stupid, but I still do not see the difference.
Both mi and prop are local variables which are 'lifted' to a field, right
when
the delegate is created. So there shouldn't be any difference, should it?


But prop is changing every time around the loop, mi is local to the loop
and so is fixed for each iteration.

If you look at the generated code (e.g in reflector) you will see that in
the case of using the iterator, the generated class is instantiated once
outside of the loop as that is the scope of the iterator.

In the case of the local variable, the generated class is instantiated
inside the loop as that is the scope of mi.#

So for the iterator the single integer value ends up as the last iterated
one, for the local variable its each value is captured in a separate
instance.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Nov 17 '05 #5
"cody" <de********@gmx.de> wrote in message
news:Ow**************@TK2MSFTNGP12.phx.gbl...
Ok I had a look in reflector and I now see the problem. Since in generated
code there is no local variable "PropertyInfo prop" but instead just a
call to "enumerable.Current" so there is nothing to 'lift'.

This maybe right from the view of the ILCode but it is toally wrong from
the view of the sourcecode since "PropertyInfo prop" is a readonly
variable from the programmer's view.

Iam the opinion that is is a very dangerous pitfall. If MS won't fix that,
they should at least throw a compiler error when a foreach iterator is
used in a anonymous method.

What do you think about that?


Surely its simply following standard scoping rules - its declaring the class
at the outermost scope of the local variables that are used within the anon
delegate. It obviously can't do it within the scope as the outermost one
wouldn't be in scope at that point.

So what you are asking for is special casing of your situation (I'm not
lambasting you for this just stating what you are asking). This is an
equally valid construct:

int i = 0;
int[] ii = int[3] { 1, 2, 3};

foreach ( i in ii )
{
// blah
}

this has basically the same scope as your iterator version - what would you
have the compiler do here?

I can understand your frustration, the closure like feature of anon
delegates can lead to some weird behavior if you don't know whats ahppening
behind the scenes. But asking fofr compiler special casig of your construct
is alot to ask (but it has been done before)

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk
Nov 17 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Werner Partner | last post by:
I use a page created by php. It should show two pictures of a person an a short text. If there are no picture, nothing is shown, if there is no...
2
by: Marcos Stefanakopolus | last post by:
In C# is there any way to use the concept of delegates to have multiple implementations of a particular block of code, so that you can choose between...
3
by: anonymous | last post by:
I believe I ran into an interesting way to create memory leaks in C# 2.0 using anymous delegates. Here is a sample of the code in question. ...
4
by: Harold Howe | last post by:
I am running into a situation where the compiler complains that it cannot infer the type parameters of a generic method when one of the function...
7
by: Bill Woodruff | last post by:
I've found it's no problem to insert instances of named delegates as values into a generic dictionary of the form : private Dictionary<KeyType,...
22
by: PJ6 | last post by:
I just learned about anonymous methods and was taken aback to discover that they are only available in C#. What, is there still a stigma against...
15
by: Matt | last post by:
Hi There, Can anyone explain me the real advantages of (other than syntax) lambda expressions over anonymous delegates? advantage for one over the...
4
by: Frankie | last post by:
I have just gotten up to speed on what anonymous methods are (syntax, capabilities, etc), and how they can be used with /called via delegates. ...
1
by: ktrvnbq02 | last post by:
Hi, I recently came to debug some old code that was causing a StackOverflowException. The code in question makes significant use of recursion...
0
by: teenabhardwaj | last post by:
How would one discover a valid source for learning news, comfort, and help for engineering designs? Covering through piles of books takes a lot of...
0
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
0
by: CD Tom | last post by:
This happens in runtime 2013 and 2016. When a report is run and then closed a toolbar shows up and the only way to get it to go away is to right...
0
by: CD Tom | last post by:
This only shows up in access runtime. When a user select a report from my report menu when they close the report they get a menu I've called Add-ins...
0
jalbright99669
by: jalbright99669 | last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was...
0
by: Matthew3360 | last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function. Here is my code. ...
2
by: Matthew3360 | last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
0
by: AndyPSV | last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.