Paulo Morgado

.NET Development & Architecture

This Blog

Syndication

Search

Sponsored By

Tags

News

Unit Test Today! Get Typemock Isolator!

Projects

Books

 

Visitors

Visitor Locations

Community

Email Notifications

Archives

Profile

Disclaimer

The opinions and viewpoints expressed in this site are mine and do not necessarily reflect those of Microsoft, my employer or any community that I belong to. Any code or opinions are offered as is. Products or services mentioned are purchased by me, made available to me by my employer or the manufacturer/vendor which doesn't influence my opinion in any way.

C# And Visual Basic Generate Different Expression Trees

(This was pointed out to me by Frans Bouma and explained by Jon Skeet)

Imagine you have this set of classes:

public class A
{
    public virtual string P
    {
        get { return "A"; }
    }
}

public class B : A
{
}

public class C : B
{
    public override string P
    {
        get { return "C"; }
    }
}

And this class:

public static class Reporter
{
    public static void Report<T>(T target, Expression<Func<T, string>> expression)
    {
        Console.WriteLine("Expression: {0}", expression);
        Console.WriteLine("\tDeclaring Type: {0}", ((expression as LambdaExpression).Body as MemberExpression).Member.DeclaringType);
        Console.WriteLine("\tInvocation Result: {0} for {1}", expression.Compile().Invoke(target), target.GetType());
        Console.WriteLine();
    }
}

The above class writes to the console the lambda expression, the declaring type of the property and the value of the property for the target and the target’s type.

Now, let’s look at what happens when used from this C# code:

Reporter.Report(new C(), (A a) => a.P);
Reporter.Report(new C(), (B b) => b.P);
Reporter.Report(new C(), (C c) => c.P);

Reporter.Report(new B(), (A a) => a.P);
Reporter.Report(new B(), (B b) => b.P);

Reporter.Report(new A(), (A a) => a.P);

The output will be:

Expression: a => a.P
        Declaring Type: A
        Invocation Result: C for C

Expression: b => b.P
        Declaring Type: A
        Invocation Result: C for C

Expression: c => c.P
        Declaring Type: A
        Invocation Result: C for C

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for B

Expression: b => b.P
        Declaring Type: A
        Invocation Result: A for B

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for A

On the other hand, if used from the equivalent Visual Basic code:

Reporter.Report(New C(), Function(a As A) a.P)
Reporter.Report(New C(), Function(b As B) b.P)
Reporter.Report(New C(), Function(c As C) c.P)

Reporter.Report(New B(), Function(a As A) a.P)
Reporter.Report(New B(), Function(b As B) b.P)

Reporter.Report(New A(), Function(a As A) a.P)

The output will be:

Expression: a => a.P
        Declaring Type: A
        Invocation Result: C for C

Expression: b => b.P
        Declaring Type: A
        Invocation Result: C for C

Expression: c => c.P
        Declaring Type: C
        Invocation Result: C for C

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for B

Expression: b => b.P
        Declaring Type: A
        Invocation Result: A for B

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for A

Why the differences? It’s because of each language’s specification and compiler:

  • The C# compiler will issue a virtual call to the virtual member in the class where it’s declared as virtual.
  • The Visual Basic compiler will issue a virtual call to the overriding member on the class that overrides it.

Published Mon, Aug 4 2008 1:23 by Paulo Morgado

Comments

# field_other@ Sunday, December 28, 2008 1:43 PM

www.message_bocrelnoeltl.com

nick_vardar

Leave a Comment

(required) 
(required) 
(optional)
(required)