Created
September 30, 2014 09:02
-
-
Save kappa7194/21c3390130f3e8d54fc2 to your computer and use it in GitHub Desktop.
Compare nullable type expressions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
Expression<Func<DateTime?>> foo = () => DateTime.MaxValue; | |
Expression<Func<DateTime>> bar = () => DateTime.MinValue; | |
Expression<Func<string>> baz = () => string.Empty; | |
GreaterThan(foo.Body, bar.Body); // Works. | |
GreaterThan(foo.Body, baz.Body); // Throws. | |
GreaterThan(bar.Body, baz.Body); // Throws. | |
} | |
static Expression GreaterThan(Expression firstExpression, Expression secondExpression) | |
{ | |
if (firstExpression == null) | |
{ | |
throw new ArgumentNullException("firstExpression"); | |
} | |
if (secondExpression == null) | |
{ | |
throw new ArgumentNullException("secondExpression"); | |
} | |
var isFirstExpressionNullable = IsNullableExpression(firstExpression); | |
var isSecondExpressionNullable = IsNullableExpression(secondExpression); | |
if (isFirstExpressionNullable && !isSecondExpressionNullable) | |
{ | |
secondExpression = FixExpressionType(secondExpression, firstExpression); | |
} | |
else if (!isFirstExpressionNullable && isSecondExpressionNullable) | |
{ | |
firstExpression = FixExpressionType(firstExpression, secondExpression); | |
} | |
if (!AreSameType(firstExpression, secondExpression)) | |
{ | |
throw new InvalidOperationException( | |
string.Format( | |
CultureInfo.InvariantCulture, | |
"Supplied expressions are of different types. First expression is [{0}], second expression is [{1}]", | |
firstExpression.Type.AssemblyQualifiedName ?? firstExpression.Type.FullName, | |
secondExpression.Type.AssemblyQualifiedName ?? secondExpression.Type.FullName)); | |
} | |
return Expression.GreaterThan(firstExpression, secondExpression); | |
} | |
static bool IsNullableExpression(Expression expression) | |
{ | |
if (expression == null) | |
{ | |
throw new ArgumentNullException("expression"); | |
} | |
return expression.Type.IsGenericType && expression.Type.GetGenericTypeDefinition() == typeof(Nullable<>); | |
} | |
static Expression FixExpressionType(Expression notNullableExpression, Expression nullableExpression) | |
{ | |
if (notNullableExpression == null) | |
{ | |
throw new ArgumentNullException("notNullableExpression"); | |
} | |
if (nullableExpression == null) | |
{ | |
throw new ArgumentNullException("nullableExpression"); | |
} | |
if (IsNullableExpression(notNullableExpression)) | |
{ | |
throw new ArgumentException( | |
string.Format( | |
CultureInfo.InvariantCulture, | |
"Not nullable expression is nullable: [{0}].", | |
notNullableExpression.Type.AssemblyQualifiedName ?? notNullableExpression.Type.FullName), | |
"notNullableExpression"); | |
} | |
if (!IsNullableExpression(nullableExpression)) | |
{ | |
throw new ArgumentException( | |
string.Format( | |
CultureInfo.InvariantCulture, | |
"Nullable expression is not nullable: [{0}].", | |
nullableExpression.Type.AssemblyQualifiedName ?? nullableExpression.Type.FullName), | |
"nullableExpression"); | |
} | |
if (!AreSameType(nullableExpression, notNullableExpression)) | |
{ | |
throw new InvalidOperationException( | |
string.Format( | |
CultureInfo.InvariantCulture, | |
"Supplied expressions are of different types. Not nullable expression is [{0}], nullable expression is [{1}].", | |
notNullableExpression.Type.AssemblyQualifiedName ?? notNullableExpression.Type.FullName, | |
nullableExpression.Type.AssemblyQualifiedName ?? nullableExpression.Type.FullName)); | |
} | |
return Expression.Convert(notNullableExpression, nullableExpression.Type); | |
} | |
static bool AreSameType(Expression nullableExpression, Expression notNullableExpression) | |
{ | |
if (nullableExpression == null) | |
{ | |
throw new ArgumentNullException("nullableExpression"); | |
} | |
if (notNullableExpression == null) | |
{ | |
throw new ArgumentNullException("notNullableExpression"); | |
} | |
return Nullable.GetUnderlyingType(nullableExpression.Type) == notNullableExpression.Type; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment