views:

71

answers:

2

following is my code, i don't know why DateTime can not change to Object , any idea to resolve this problem?

    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 .... 
    }
A: 

You're attempting to convert a delegate type Func<Test, DateTime> expression1 to a delegate type Func<Test, object>, not the DateTime field to object.

If this was your original intention, use the lambda expression syntax instead, like so:

Func<Test, object> s = p => p.CreatedTime;
James Dunne
thank you for your help , i understand your meaning,
Clover
but i want to understand Generic Covariant .
Clover
Func<Object, Test2> can change to Func<String, Test1> because Test2 derived Test1 , i think all of types derived System.Object , why i can not change Func<Object, DateTime> to Func<String, Object>
Clover
Your question was worded unclearly so I apparently answered the wrong implicit question. Mehrdad has your correct answer. DateTime as a value type cannot be converted to a reference type in this case.
James Dunne
+6  A: 

DateTime is a value type. Converting a value type to a reference type (object in this case) is a representation-changing conversion. It requires boxing the value type. For reference types, this is not the case. CLR implements reference with pointers and all pointers have the same size. A reference to a derived class is merely interpreted as a reference to the base class. For this reason, you cannot use covariance like that on value types.

Theoretically, it would have been possible for the compiler to generate an intermediate function like:

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;

But the resulting delegate would point to an entirely different function causing bad things like not obeying delegate equality rules in C# spec. The design team has decided against generating such a function.

Mehrdad Afshari
@Mehrdad : "all pointers have the same size" , i am not able to get this. Can you please explain?
saurabh
@saurabh: Forget pointers entirely for a second; that's an implementation detail. Think about this: at IL level, converting a value type to a reference type requires a `box` instruction while converting a reference type to its base class is a no-op. No conversion is needed at runtime for reference types. You cast reference types in the inheritance hierarchy in C# to make the compiler happy; you don't make it to generate code for the cast.
Mehrdad Afshari