【发布时间】:2013-11-12 05:31:03
【问题描述】:
学习 LINQ 表达式我发现了一个奇怪的行为。请看下面的课程。它可能看起来不是很方便,但这只是一个例子。
class IntTestClass
{
public int Id { get; private set; }
Func<IntTestClass, bool> check;
public IntTestClass(int _id)
{
Id = _id;
Expression<Func<IntTestClass, int>> GetId = tc => tc.Id;
Expression<Func<int, bool>> e1 = i => i.Equals(Id);
var equals1 = (e1.Body as MethodCallExpression).Method;
string s1 = equals1.ToString();
Console.WriteLine(s1);
var x1 = Expression.Call(Expression.Constant(Id), equals1, GetId.Body);
var exp1 = (Expression<Func<IntTestClass, bool>>)
Expression.Lambda(x1, GetId.Parameters.ToArray());
check = exp1.Compile();
}
public bool Check(IntTestClass t)
{
var result = check(t);
Console.WriteLine(result);
return result;
}
}
只是为了运行一个可以使用的测试:
var intTestClass= new IntTestClass(0);
intTestClass.Check(new IntTestClass(0)); //true
intTestClass.Check(new IntTestClass(1)); //false
然后我尝试使这个类通用:
class TestClass<T>
{
public T Id { get; private set; }
public TestClass(T _Id)
{
Id = _Id;
Expression<Func<TestClass<T>, T>> GetId = tc => tc.Id;
Expression<Func<T, bool>> e1 = i => i.Equals(Id);
var equals1 = (e1.Body as MethodCallExpression).Method;
string s1 = equals1.ToString();
Console.WriteLine(s1);
var x1 = Expression.Call(Expression.Constant(Id), equals1, GetId.Body);
....
}
....
}
所以当我尝试运行类似的代码时:
var testClass = new TestClass<int>(0);
它在构造函数中初始化x1 变量时抛出异常,说
“System.Int32”类型的表达式不能用于“Boolean Equals(System.Object)”方法的“System.Object”类型参数
所以看起来TestClass<T>构造函数中的equals1(包含Equals方法的MethodInfo)是Boolean Equals(System.Object)
但在IntTestClass 构造函数中equals1 是Boolean Equals(Int32)。
为什么会这样?在运行时的泛型类中,T 的类型为 System.Int32。为什么e1 变量中的表达式使用来自System.Object 类的Equals,而不是来自System.Int32?
【问题讨论】:
标签: c# linq generics expression