簡體   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