【问题标题】:Lambda expression type inference is different in inheritance chain. Why?Lambda 表达式类型推断在继承链中有所不同。为什么?
【发布时间】:2011-06-02 01:51:35
【问题描述】:

给定以下类:

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”属性设置器中的 lambda 表达式推断基类的泛型类型,但对于 Class3,编译器推断基类,而不仅仅是基类的泛型类型。为什么是这样?代码示例中推断类型的标准是什么。谢谢。

【问题讨论】:

    标签: c# lambda type-inference


    【解决方案1】:

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

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

    在 Class3 中,传递给基类的 TObject 是 Class2,而不是 Class3。因此,lambda 的参数被推断出来,但它被推断为 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); }
        }
    }
    

    【讨论】:

    • 嗯,你说得对,克里斯,TObject 类型(在 Class1 中)将始终是 Class2,无论链有多深。现在,我到底是怎么错过的?不幸的是,您的解决方案在我的情况下不起作用,因为这意味着 Class3 将不再继承 Class2 的属性。最简单的解决方案是将 C3 转换为“Class3”。我的问题是关于我认为的推理不一致,但正如你所指出的,它根本不是不一致的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 2010-09-20
    • 2019-06-06
    相关资源
    最近更新 更多