Lambda表达式类型推断在继承链中是不同的。为什么?

时间:2011-06-02 01:51:35

标签: c# lambda type-inference

鉴于以下类别:

public class Class1<TObject> {
    protected void MethodA<TType>(Expression<Func<TObject, TType>> property, ref TType store, TType value) {
    }
}

public class Class2<TObject> : Class1<Class2<TObject>>{
    private int _propertyInt;
    public int PropertyInt {
        get { return _propertyInt; }
        set { MethodA(c2 => c2.PropertyInt, ref _propertyInt, value); }
    }
}

public class Class3 : Class2<Class3> {
    private float _propertyFloat;
    public float PropertyFloat {
        get { return _propertyFloat; }
        set { MethodA(c3 => c3.PropertyFloat, ref _propertyFloat, value); }
    }
}

对于Class2,C#编译器在'PropertyInt'属性setter中推断lambda表达式的基类的泛型类型,但对于Class3,编译器推断基类,而不仅仅是基类的泛型类型。为什么是这样?代码示例中的推断类型的标准是什么。感谢。

1 个答案:

答案 0 :(得分:4)

首先,TObject泛型参数在Class1中定义。 那个 TObject在Class1中用作MethodA中的类型参数。

在Class2中,传递给基类(Class1)的TObject是Class2,因此lambda可以推断出本地属性_propertyInt。

在Class3中,传递给基类的TObject是Class2,而不是Class3。因此,推断出lambda的参数,但它被推断为Class2,而不是Class3。

Class2 有一个名为TObject的类型参数的事实完全是巧合 - 我认为你期望传递给TObject的任何东西都会传递给Class1,而不是。 / p>

如果按如下方式定义了Class3,它将起作用:

public class Class3 : Class1<Class3> { ... }

鉴于评论,那么我可以提供这种基于扩展方法的解决方案,(假设类型参数仅用于实现此目的):

public class Class1
{
}

public static class StaticClass1
{
    public static void MethodA<TZen, TType>(this TZen zen, Expression<Func<TZen, TType>> property, ref TType store, TType value) where TZen : Class1
    {
        // Do whatever here...
    }
}

public class Class2 : Class1
{
    private int _propertyInt;
    public int PropertyInt
    {
        get { return _propertyInt; }
        set { this.MethodA(c2 => c2.PropertyInt, ref _propertyInt, value); }
    }
}

public class Class3 : Class2
{
    private float _propertyFloat;
    public float PropertyFloat
    {
        get { return _propertyFloat; }
        set { this.MethodA(c3 => c3.PropertyFloat, ref _propertyFloat, value); }
    }
}