代码之家  ›  专栏  ›  技术社区  ›  Clover

C一般协变误差

  •  1
  • Clover  · 技术社区  · 15 年前

    以下是我的代码, 我不知道为什么datetime不能更改为object, 有办法解决这个问题吗?

        public class Test
        {
            public DateTime CreatedTime { get; set; }
        }
        public class Test1
        {
    
        }
        public class Test2 : Test1
        {
        }
        static void Main(string[] args)
        {
    
            Func<Test, ArgumentException> fn1 = null;
            Func<Test, Exception> fn2 = fn1;// success 
    
            Func<Test, Test2> fn3 = null;
            Func<Test, Test1> fn4 = fn3;//success  
    
            Func<Test, DateTime> expression1 = p => p.CreatedTime;
            Func<Test, object> s = expression1; // Cannot implicitly convert type 'System.Func<IlReader.Program.Test,System.DateTime>' to 'System.Func<IlReader.Program.Test,object>'    
            Func<Test, ValueType> s2 = expression1; // cannot implicatily convert .... 
        }
    
    2 回复  |  直到 15 年前
        1
  •  6
  •   Mehrdad Afshari    15 年前

    DateTime 是值类型。将值类型转换为引用类型( object 在本例中)是一种表示形式,用于更改转换。它需要对值类型进行装箱。对于引用类型,情况并非如此。clr使用指针实现引用,并且所有指针的大小都相同。对派生类的引用仅解释为对基类的引用。因此,不能对值类型使用类似的协方差。

    理论上,编译器可以生成一个中间函数,如:

    object compilerGeneratedFunction(Test t) {
        return (object)anonymousFunctionThatReturnsDateTime(t);
        // The above cast can be implicit in C# but I made it explicit to demonstrate
        // boxing that has to be performed.
    }
    
    Func<Test, DateTime> convertedFunction = compilerGeneratedFunction;
    

    但是,生成的委托将指向一个完全不同的函数,这会导致不遵守C规范中的委托相等规则等糟糕的事情。设计团队决定不生成这样的函数。

        2
  •  0
  •   James Dunne    15 年前

    您正试图转换委托类型 Func<Test, DateTime> expression1 到委托类型 Func<Test, object> 而不是 DateTime 字段到 object .

    如果这是您的初衷,请改用lambda表达式语法,如下所示:

    Func<Test, object> s = p => p.CreatedTime;
    
    推荐文章