C#反射调用HashSet的Overlaps方法时Expression表达式参数错误问题
问题排查结果
一共有两处错误:
- 第一处:
Overlaps是HashSet<T>的实例方法,不是静态方法,你使用的Expression.Call重载适配的是静态方法调用,实例方法调用需要把实例对象作为Call方法的第一个入参。原来的写法把两个参数都当成了方法的入参,漏掉了隐式的this实例参数。 - 第二处:Lambda的委托类型定义错误,
Overlaps方法返回值为bool,你定义的Func<HashSet<int>, HashSet<int>>表示返回值为HashSet<int>,参数数量也不匹配,需要修正为Func<HashSet<int>, HashSet<int>, bool>。
修正后代码
var bigSet = Enumerable.Range(1, 10).ToList().ToHashSet(); var smallSet = Enumerable.Range(3, 1).ToList().ToHashSet(); var p1 = Expression.Parameter(typeof(HashSet<int>)); var p2 = Expression.Parameter(typeof(HashSet<int>)); // 获取方法时指定参数类型,避免重载匹配错误 MethodInfo overlap = typeof(HashSet<int>).GetMethod("Overlaps", new[] { typeof(IEnumerable<int>) }); // 实例方法调用:第一个参数是实例(对应this),第二个是方法信息,后面是方法入参 var body = Expression.Call(p1, overlap, p2); // 修正委托类型,最后一个泛型参数是返回值类型bool var lam = Expression.Lambda<Func<HashSet<int>, HashSet<int>, bool>>(body, p1, p2); var invocationTest = overlap.Invoke(bigSet, new object[] { smallSet }); Console.WriteLine(invocationTest); var comp = lam.Compile(); var x = comp(bigSet, smallSet); Console.WriteLine(x); // 输出为true,和反射调用结果一致
内容的提问来源于stack exchange,提问作者plusss
相关产品推荐
相关产品推荐

