@ -28,6 +28,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
@@ -28,6 +28,8 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
Test ( ) ;
var twice = GetExpression ( Expression . Constant ( 2 ) ) . Compile ( ) ;
Console . WriteLine ( twice ( 2 1 ) ) ;
TypeParameterComparisons ( ) ;
ValueTypeComparisons ( ) ;
}
static void Test ( )
@ -43,5 +45,62 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
@@ -43,5 +45,62 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Correctness
ParameterExpression parameterExpression = Expression . Parameter ( typeof ( int ) , "x" ) ;
return Expression . Lambda < Func < int , int > > ( Expression . Multiply ( parameterExpression , factor ) , parameterExpression ) ;
}
// A comparison of two type parameters, which no lambda can spell: `v == other` is CS0019
// for a type parameter, and boxing both operands compiles but compares box identity,
// where Equal on two T compares values once T is a value type. The int instantiation
// below is what tells those two apart.
static Expression < Func < T , bool > > EqualsValue < T > ( T other )
{
ParameterExpression parameterExpression = Expression . Parameter ( typeof ( T ) , "v" ) ;
return Expression . Lambda < Func < T , bool > > (
Expression . Equal ( parameterExpression , Expression . Constant ( other , typeof ( T ) ) ) , parameterExpression ) ;
}
static Expression < Func < T , bool > > NotEqualsValue < T > ( T other )
{
ParameterExpression parameterExpression = Expression . Parameter ( typeof ( T ) , "v" ) ;
return Expression . Lambda < Func < T , bool > > (
Expression . NotEqual ( parameterExpression , Expression . Constant ( other , typeof ( T ) ) ) , parameterExpression ) ;
}
static void TypeParameterComparisons ( )
{
object a = new object ( ) ;
object b = new object ( ) ;
Console . WriteLine ( EqualsValue ( a ) . Compile ( ) ( a ) ) ;
Console . WriteLine ( EqualsValue ( a ) . Compile ( ) ( b ) ) ;
Console . WriteLine ( NotEqualsValue ( a ) . Compile ( ) ( a ) ) ;
Console . WriteLine ( NotEqualsValue ( a ) . Compile ( ) ( b ) ) ;
Console . WriteLine ( EqualsValue ( 4 2 ) . Compile ( ) ( 4 2 ) ) ;
Console . WriteLine ( EqualsValue ( 4 2 ) . Compile ( ) ( 4 3 ) ) ;
}
// The same shape on value types that are not type parameters: decimal and a nullable
// both compare as themselves, and boxing either would turn the comparison into a
// reference comparison of two boxes.
static Expression < Func < decimal , bool > > GreaterThanDecimal ( decimal limit )
{
ParameterExpression parameterExpression = Expression . Parameter ( typeof ( decimal ) , "v" ) ;
return Expression . Lambda < Func < decimal , bool > > (
Expression . GreaterThan ( parameterExpression , Expression . Constant ( limit , typeof ( decimal ) ) ) , parameterExpression ) ;
}
static Expression < Func < int? , bool > > EqualsNullable ( int? other )
{
ParameterExpression parameterExpression = Expression . Parameter ( typeof ( int? ) , "v" ) ;
return Expression . Lambda < Func < int? , bool > > (
Expression . Equal ( parameterExpression , Expression . Constant ( other , typeof ( int? ) ) ) , parameterExpression ) ;
}
static void ValueTypeComparisons ( )
{
Console . WriteLine ( GreaterThanDecimal ( 1 m ) . Compile ( ) ( 2 m ) ) ;
Console . WriteLine ( GreaterThanDecimal ( 1 m ) . Compile ( ) ( 0 m ) ) ;
Console . WriteLine ( EqualsNullable ( 1 ) . Compile ( ) ( 1 ) ) ;
Console . WriteLine ( EqualsNullable ( 1 ) . Compile ( ) ( 2 ) ) ;
Console . WriteLine ( EqualsNullable ( 1 ) . Compile ( ) ( null ) ) ;
Console . WriteLine ( EqualsNullable ( null ) . Compile ( ) ( null ) ) ;
}
}
}