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' のパラメーターには使用できません
したがって、コンストラクターの(メソッドequals1
を含む)はMethodInfo
Equals
TestClass<T>
Boolean Equals(System.Object)
しかし、IntTestClass
コンストラクターequals1
ではBoolean Equals(Int32)
.
どうしてこんなことに?実行時のジェネリック クラスでT
は、タイプはSystem.Int32
. e1
変数の式がクラスEquals
から使用されるのに、からではないのはなぜですか?System.Object
System.Int32