我有一个样本Data课
public class Data
{
public int TestInt { get; set; }
public bool TestBool { get; set; }
public string TestString { get; set; }
public Data() { TestInt = 10; TestBool = true; TestString = "test"; }
}
Run Code Online (Sandbox Code Playgroud)
并且是一种扩展方法
public static void Method<T>(this T item, params Expression<Func<T, object>>[] properties)
{
/* Some stuff */
}
Run Code Online (Sandbox Code Playgroud)
我这样用
Data data = new Data();
data.Method(x => x.TestInt, x => x.TestBool, x => x.TestString);
Run Code Online (Sandbox Code Playgroud)
我Method<T>确实收到3个属性,但它稍微改为:
properties[0] = x => Convert(x.TestId);
properties[1] = x => Convert(x.TestBool);
properties[2] = x => x.TestString;
Run Code Online (Sandbox Code Playgroud)
如您所见,该TestString部分没有变化.我尝试将我的属性更改为params Expression<Func<T, bool>>[]和params Expression<Func<T, int>>[]只传递相应的参数,它工作正常.我知道这个问题来自转换成一个object但我无法弄明白.
由于Int32和Boolean都不是引用类型,因此整个表达式树需要将它们显式转换为object.
在使用常规 C# 编译器进行编译时,有一些隐式操作可用,而其他一些则在实现表达式树时需要显式操作。
你想测试自己这个事实吗?
public struct A {}
public class B { }
public class C
{
public A A { get; set; }
public B B { get; set; }
}
C c = new C();
Expression<Func<C, object>> expr1 = some => some.A; // Convert(some.A)
Expression<Func<C, object>> expr2 = some => some.B; // some.B
Run Code Online (Sandbox Code Playgroud)
归根结底,常规 C# 编译器实现了一些技巧来转换值类型以适应object(引用类型)。也许这个问答“ ValueTypes 如何从 Object (ReferenceType) 派生并仍然是 ValueTypes? ” Eric Lippert 的回答可能对您很有趣。
没有办法强制表达式保持不变吗?
不。您应该处理两种情况:使用和不使用强制转换访问属性。
如果您想分析原始表达,一种可能的方法是手动删除Convert表达。
在 中Method,您可能会得到UnaryExpression一个NodeType=Convert。如果是这样,只需检查该表达式的 Operand 属性。
| 归档时间: |
|
| 查看次数: |
991 次 |
| 最近记录: |