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