Вывод типа лямбда-выражения отличается в цепочке наследования. Зачем? - PullRequest
4 голосов
/ 02 июня 2011

Даны следующие классы:

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', но для Class3 компилятор выводит базовый класс, а не только универсальный тип базового класса. Почему это? Каковы критерии для предполагаемого типа в примере кода. Спасибо.

1 Ответ

4 голосов
/ 02 июня 2011

Во-первых, универсальный параметр TObject определен в Class1. То, что TObject используется в Class1 в качестве аргумента типа в MethodA.

В Class2 объект TObject, переданный базе (Class1), является классом 2, и поэтому лямбда-выражение может выводить локальное свойство _propertyInt.

В Class3 объект TObject, переданный базе, являетсяКласс2, а не Класс3.Следовательно, аргумент лямбды выводится, но выводится как Class2, а не Class3.

Тот факт, что Class2 также имеет параметр типа с именем TObject, совершенно случайен - я думаю, выожидают, что все, что передано этому TObject, будет транзитивно передано в Class1, а это не так.

Если вы определили 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); }
    }
}
...