简体   繁体   English

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

[英]How to prevent Convert in generated expression for type parameter is interface

Here is the example code:这是示例代码:

    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());
        }
    }

The output of the expression: a => (Convert(a, A).MyProperty > 0) output 的表达式: a => (Convert(a, A).MyProperty > 0)

And I decompiled the code above and I got below:我反编译了上面的代码,得到了下面的结果:

public class C<T> where T : A
{
    public Expression<Func<T, bool>> Expression { get; } = (T a) => ((A)a).MyProperty > 0;

}

As you can see, the compiler added a cast option ((A)a) to the expression, that is what I DO NOT want, so the question is how can I tell the compiler NOT to do that?如您所见,编译器在表达式中添加了一个强制转换选项((A)a) ,这是我想要的,所以问题是我如何告诉编译器要这样做?

There is no way to "tell the compiler" not to do this, but you can construct the expression tree directly:没有办法“告诉编译器”不要这样做,但可以直接构造表达式树:

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>>;
    }
}

Looks like the compiler is emitting the Convert because of the possibility of the generic type parameter to be struct (value type), even though the manual approach demonstrated by another answer proves that it is unnecessary.看起来编译器正在发出Convert ,因为泛型类型参数可能是struct (值类型),即使另一个答案演示的手动方法证明它是不必要的。

But is is what it is.但就是这样。 So the only way currently to tell compiler to not generate Convert (cast) is to put class constraint:因此,目前告诉编译器不生成Convert (cast) 的唯一方法是放置class约束:

where T : class, A

Now the output of the original sample expression will be a => (a.MyProperty > 0)现在原始样本表达式的 output 将是a => (a.MyProperty > 0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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