一般打字表达怪异

时间:2008-11-11 16:08:36

标签: vb.net linq generics

下面的代码给出了一个错误:

当创建表达式e但没有为类型'ConsoleApplication1.IKeyed`1 [TKey]'
定义属性'Int32 Key'但是很好当func f被创建时,任何人都可以解释为什么以及是否有办法解决它?

Module Module1
    Sub Main()
        Dim g = New keyedThingGetter(Of KeyedThing, Integer)
        Dim thing = g.getThing()
    End Sub
End Module

Public Class keyedThingGetter(Of Tthing As IKeyed(Of TKey), TKey)
    Public Function getThing() As Tthing
        Dim f As Func(Of Tthing, Boolean)
        f = Function(thing) thing.Key.Equals(1)
        Dim e As Expressions.Expression(Of Func(Of Tthing, Boolean))
        e = Function(thing) thing.Key.Equals(1)
        Return Nothing
    End Function
End Class

Public Interface IKeyed(Of TKey)
    ReadOnly Property Key() As TKey
End Interface

Public Class KeyedThing
    Implements IKeyed(Of Integer)
    Public ReadOnly Property Key() As Integer Implements IKeyed(Of Integer).Key
        Get
            Return 1
        End Get
    End Property
End Class

1 个答案:

答案 0 :(得分:1)

解决方法位于底部

这很奇怪。我仍然在研究它,但这个“大部分相当”的C#工作正常:

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();
    }
}

编辑:创建的表达式树之间存在一个有趣的区别。这是VB表达式(用Reflector反编译为C#):

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 });

这是C#版本:

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 });

区别在于第四行 - 参数的类型。在C#中,它是typeof(IKeyed<TKey>),而在VB中它是typeof(IKeyed<>)

VB编译器中的错误也许?还不确定。希望Marc G很快就能成为常驻表达树专家......

编辑:鉴于差异,我找到了解决方法。将其更改为:

Dim e as Expressions.Expression(Of Func(Of Tthing, Boolean))
e = Function(thing as IKeyed(Of TKey)) thing.Key.Equals(1))

Dim e as Expressions.Expression(Of Func(Of IKeyed(Of TKey), Boolean))
e = Function(thing) thing.Key.Equals(1))