Workaround is at the bottom
That's very odd. I'm still looking into it, but this "mostly equivalent" C# works fine:
using System;
using System.Linq.Expressions;
interface IKeyed<TKey>
{
TKey Key { get; }
}
class KeyedThing : IKeyed<int>
{
public int Key { get { return 1; } }
}
class KeyedThingGetter<TThing, TKey> where TThing : IKeyed<TKey>
{
public void GetThing()
{
Func<TThing, bool> f = thing => thing.Key.Equals(1);
Expression<Func<TThing, bool>> e = thing => thing.Key.Equals(1);
}
}
class Test
{
static void Main()
{
var g = new KeyedThingGetter<KeyedThing, int>();
g.GetThing();
}
}
EDIT: There's an interesting difference between the expression trees created. Here's the VB expression (decompiled to C# with Reflector):
Expression<Func<Tthing, bool>> expression = Expression
.Lambda<Func<Tthing, bool>> (Expression.Call(Expression.Convert
(Expression.Property(Expression.Convert(expression2 =
Expression.Parameter(typeof(Tthing), "thing"), typeof(IKeyed<>)),
(MethodInfo) methodof(IKeyed<TKey>.get_Key, IKeyed<TKey>)), typeof(object)),
(MethodInfo) methodof(object.Equals), new Expression[] {
Expression.Convert(Expression.Constant(1, typeof(int)), typeof(object)) }), new
ParameterExpression[] { expression2 });
Here's the C# version:
Expression<Func<TThing, bool>> expression = Expression
.Lambda<Func<TThing, bool>> (Expression.Call(Expression.Convert
(Expression.Property(Expression.Convert(expression2 =
Expression.Parameter(typeof(TThing), "thing"), typeof(IKeyed<TKey>)),
(MethodInfo) methodof(IKeyed<TKey>.get_Key, IKeyed<TKey>)), typeof(object)),
(MethodInfo) methodof(object.Equals), new Expression[] {
Expression.Convert(Expression.Constant(1, typeof(int)), typeof(object)) }), new
ParameterExpression[] { expression2 });
The difference is in the fourthline - the type of the parameter. In the C#, it's typeof(IKeyed<TKey>)
whereas in the VB it's typeof(IKeyed<>)
.
A bug in the VB compiler perhaps? Not sure yet. Hopefully Marc G will chime in soon, as resident expression tree expert...
EDIT: Given the difference, I worked out how to fix it. Either change it to:
Dim e as Expressions.Expression(Of Func(Of Tthing, Boolean))
e = Function(thing as IKeyed(Of TKey)) thing.Key.Equals(1))
or
Dim e as Expressions.Expression(Of Func(Of IKeyed(Of TKey), Boolean))
e = Function(thing) thing.Key.Equals(1))