Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create an instance of a Nullable<T>?

Suppose we have two classes:

public class ParentEntity
{
    public ChildEntity Child { get; set; }
}

public class ChildEntity
{
    public byte? NullableValue { get; set; }
    public byte Value { get; set; }
}

The task is to express the following code in linq expressions:

parent.Child == null ? null : parent.Child.NullableValue

To do that I tried to use the following code:

public static Expression GetCondition<TParent, TChild, TChildKey>(
                              Expression<Func<TParent, TChild>> pe, 
                              Expression<Func<TChild, TChildKey>> ce)
{
    var test = Expression.Equal(pe.Body, Expression.Constant(null));

    var ifTrue = Expression.Constant(Activator.CreateInstance<TChildKey>());
    var ifFalse = Expression.Property(pe.Body, 
                                      (ce.Body as MemberExpression).Member.Name);
    return Expression.Condition(test, ifTrue, ifFalse);
}

Running this code with

Expression<Func<ParentEntity, ChildEntity>> pe = n => n.Child;    

GetCondition(pe, n => n.Value);         // ok
GetCondition(pe, n => n.NullableValue); // throws an ArgumentException

throws an ArgumentException at the last line (at the return statement in the GetCondition), saying that the types of arguments are mismatched.

Having analysed this code I found out that Activator.CreateInstance<TChildKey>() returns object, but not TChildKey, when TChildKey is System.Nullable<T>, i.e. ifTrue.Type is object, while I expected it to be System.Nullable<byte>.

This very issue is discussed in SO: Creating a nullable object via Activator.CreateInstance returns null pointing to Reflection and Nullable

But none of these suggests anything to solve the issue.

Is there a way to create an instance of exactly System.Nullable<T> type, having value null? Or maybe there is some other way to express the original conditional expression?

like image 845
horgh Avatar asked Feb 25 '14 07:02

horgh


1 Answers

You should try Expression.New:

var ifTrue = Expression.New(typeof(Nullable<int>));
like image 123
MarcinJuraszek Avatar answered Nov 07 '22 01:11

MarcinJuraszek