2

How can I determine the type of a ConstantExpression Value when it is null? I have previously been detecting the type using the following code, but it causes a null exception when the ConstantExpression Value is null.

static Type GetType(Expression expression)
{
    //causes exception when ((ConstantExpression)expression).Value is null
    if (expression is ConstantExpression)
        return ((ConstantExpression)expression).Value.GetType(); 

    //Check other types
}

Imagine my Expression was created similar to this:-

int? value = null;
ConstantExpression expression = Expression.Constant(value);

And I would like to determine the type int?

Joe
  • 1,847
  • 2
  • 17
  • 26
  • 1
    `((ConstantExpression)expression).Type`? – Lee Jan 13 '16 at 14:54
  • Thanks, that was simple! If you add an answer I can accept it. – Joe Jan 13 '16 at 14:56
  • For reference [Correct way to check if a type is Nullable](http://stackoverflow.com/questions/8939939/correct-way-to-check-if-a-type-is-nullable) – Jason Evans Jan 13 '16 at 15:09
  • It looks like the problem is more tricky then I thought. When you get the type of a `null` value you will get `System.Object` returned (since every type ultimately derives from that type). Thus you cannot determine what the actual `type` is e.g. `int?`. I'm learning new stuff here about nullables and type checking. This is why I like StackOverflow so much. – Jason Evans Jan 13 '16 at 15:12
  • 2
    @JasonEvans that's true, but `Expression.Constant()` has an overload that takes an explicit type (as long as it's compatible with the value), so if one is going to potentially care about a `ConstantExpression`'s type, one can use that when creating it. See my answer for more. – Jon Hanna Jan 13 '16 at 15:13

1 Answers1

2
expression.Type

However, note that if you create a ConstantExpression with the factory method you show in your question, the result will be typeof(object), because when the factory examines value it's going to get a null object and not be able to call GetType() on it. If you're going to care about a ConstantExpression's type even when null you need to use the overload that passes in a type argument. This also means that if value hadn't been null the type returned would have been typeof(int), not typeof(int?):

Expression.Constant((int?)null).Type // == typeof(object)
Expression.Constant((int?)null, typeof(int?)).Type // == typeof(int?)
Expression.Constant(null, typeof(int?)).Type // == typeof(int?)
Expression.Constant((int?)3).Type // == typeof(int)
Expression.Constant((int?)3).Value.GetType() // == typeof(int)
Expression.Constant((int?)3, typeof(int?)).Type // == typeof(int?)
Expression.Constant(3, typeof(int?)).Type // == typeof(int?)

And last, but not least:

Expression.Constant(null, typeof(int)) // ArgumentException thrown, "Argument types do not match"
Jon Hanna
  • 110,372
  • 10
  • 146
  • 251