When lambda is converted to an expression tree and then compiled, invocations of interface methods on an instance of type parameter, constrained with that interface, cause boxing - by Vladimir Reshetnikov

Status : 

  Fixed<br /><br />
		This item has been fixed in the current or upcoming version of this product.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.


2
0
Sign in
to vote
ID 319387 Comments
Status Closed Workarounds
Type Bug Repros 1
Opened 12/22/2007 3:29:36 PM
Access Restriction Public

Description

Compile and run this code:

using System;
using System.Linq;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        Foo<S>();
    }

    static void Foo<T>() where T : I
    {
        Func<T, int> f = x => x.SetX() + x.X;
        Expression<Func<T, int>> e = x => x.SetX() + x.X;

        Console.WriteLine(f(default(T)));
        Console.WriteLine(e.Compile()(default(T)));
    }
}

interface I
{
    int X { get; }
    int SetX();
}

struct S : I
{
    public int X { get; private set; }
    public int SetX()
    {
        X = 7;
        return 0;
    }
}

Result:

7
0

The same lambda converted twice: (1) to a delegate type, (2) to an expression tree. The resulting delegate is invoked, the expression tree is compiled and also invoked. I expect that both invocations yield the same result. But in fact, results are different.

When an interface method is invoked on an instance of type parameter, constrained with that interface, and the type parameter is a value-type at runtime, the invocation shall not cause boxing to occur. When lambda is converted to a delegate type, the compiler correctly conforms to this rule. But when lambda is converted to an expression tree and then compiled, boxing incorrectly occurs, which leads to an unexpected and wrong result.
Sign in to post a comment.
Posted by Microsoft on 1/15/2008 at 9:29 AM
Hello nikov, once more this is Eric Lippert on the C# compiler dev team.

Thanks for your report that interface calls on constrained type parameters of value types are incorrectly boxed when in an expression tree.

There were two problems here. First, we were generating a Convert node to convert the value type to the interface type, which always causes boxing. We no longer generate the Convert node. (We already had code in place to suppress generation of the Convert on most such boxing conversions, but I missed the case of an implicit boxing caused by a type parameter conversion.)

Second, the expression tree API was verifying that type of the object of the call matched the declaring type of the methodinfo. We now allow the object to be a value type which implements the interface if the method is declared on an interface.

This fix will likely make it into the .NET / Visual Studio service packs.

Thanks again,
Eric
Posted by Microsoft on 12/23/2007 at 5:25 PM
Thanks for your feedback. We are escalating this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Thank you,
Visual Studio Product Team