[英]How to prevent Convert in generated expression for type parameter is interface
这是示例代码:
public interface A
{
int MyProperty { get; set; }
}
public class B : A
{
public int MyProperty { get; set; }
}
public class C<T> where T : A
{
public Expression<Func<T, bool>> Expression { get; } = a => a.MyProperty > 0;
}
class Program
{
static void Main(string[] args)
{
var cExpression = new C<B>();
Console.WriteLine(cExpression.Expression.ToString());
}
}
output 的表达式: a => (Convert(a, A).MyProperty > 0)
我反编译了上面的代码,得到了下面的结果:
public class C<T> where T : A
{
public Expression<Func<T, bool>> Expression { get; } = (T a) => ((A)a).MyProperty > 0;
}
如您所见,编译器在表达式中添加了一个强制转换选项((A)a)
,这是我不想要的,所以问题是我如何告诉编译器不要这样做?
没有办法“告诉编译器”不要这样做,但可以直接构造表达式树:
public class C<T> where T : A {
private static readonly MethodInfo s_propGetter = typeof(A).GetProperty(nameof(A.MyProperty)).GetMethod;
public Expression<Func<T, bool>> Expr { get; private set; }
public C() {
var param = Expression.Parameter(typeof(T), "a");
Expr = Expression.Lambda(
typeof(Func<T, bool>),
Expression.GreaterThan(Expression.Property(param, s_propGetter), Expression.Constant(0)),
new[] {param}
) as Expression<Func<T, bool>>;
}
}
看起来编译器正在发出Convert
,因为泛型类型参数可能是struct
(值类型),即使另一个答案演示的手动方法证明它是不必要的。
但就是这样。 因此,目前告诉编译器不生成Convert
(cast) 的唯一方法是放置class
约束:
where T : class, A
现在原始样本表达式的 output 将是a => (a.MyProperty > 0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.