繁体   English   中英

如何防止在生成的类型参数表达式中转换是接口

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM