Skip to content

Instantly share code, notes, and snippets.

@kappa7194
Created September 30, 2014 09:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kappa7194/21c3390130f3e8d54fc2 to your computer and use it in GitHub Desktop.
Save kappa7194/21c3390130f3e8d54fc2 to your computer and use it in GitHub Desktop.
Compare nullable type expressions
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