我准备以编程方式绑定Expression.Lambda (因为未知/可变类型参数),并发现如果目标方法使用params,则反射调用与直接调用略有不同。
首先,在正式文件中,“签名”(虽然这更像是XML):
public static
System.Linq.Expressions.Expression<TDelegate>
Lambda<TDelegate>(
System.Linq.Expressions.Expression body,
params System.Linq.Expressions.ParameterExpression[]? parameters
);注意,第二个param标记为可选,我们可以编写Expression.Lambda<T>(...)。如果在Visual中,转到反汇编声明列表,则可以看到以下内容:
public static
Expression<TDelegate>
Lambda<TDelegate>(
Expression body,
params ParameterExpression[] parameters
);第二个参数不再标记为选项。现在,当我试图使用反射调用此方法时,如下所示:
var lambdaFactory = typeof(Expression)
.GetMethods()
// Filter overloads
.Single(x => x.ToString() == "System.Linq.Expressions.Expression`1[TDelegate] Lambda[TDelegate](System.Linq.Expressions.Expression, System.Linq.Expressions.ParameterExpression[])")
.MakeGenericMethod(myTypeArgument);
var lambda = (LambdaExpression) lambdaFactory.Invoke(
null,
new object[] {
...
// ,null
}
);我找到TargetParameterCountException: Parameter count mismatch.了。但是,如果将null作为另一个参数添加,它将完美地工作。
这对我来说有点奇怪。为什么MS文档使用? (可选标记)?与regualr选项参数类似,params参数真的是可选的,如string Foo(int a = 1); var result = Foo();吗?还是只是一种语法糖?这就是为什么我可以在编辑器中直接调用Expression.Lambda<T>(...),但是编译的代码可能是不同的(这也与反射系统兼容)。如果是这样的话,这是否意味着方法总是接收null值,即使我没有指定值?但是,如果一个方法使用params参数,而没有传递任何内容,则来自方法主体的参数是一个带有.Count == 0的有效数组,而不是null。使用反射传递null是安全的,还是应该创建一个空对象数组?
发布于 2020-12-25 00:36:24
文档中的?表示可空引用类型,而不是可选参数。可空引用类型纯粹是一种“编译时检查”,而且在运行时,它们与常规的旧引用类型没有什么不同。
可空引用类型不是新的类类型,而是现有引用类型的注释。编译器使用这些注释来帮助您在代码中查找潜在的空引用错误。非空引用类型和可空引用类型之间没有运行时的区别。编译器不添加任何非空引用类型的运行时检查。其好处在于编译时分析。编译器生成警告,帮助您在代码中查找和修复潜在的空错误。您可以声明您的意图,当您的代码违反此意图时,编译器会警告您。
这解释了为什么当您查看“反汇编声明列表”时,?会消失。
所有?告诉您的是,您可以将null传递给该参数,并且该方法仍将工作。
在这种情况下,传递null的另一种方法是传递一个空的ParameterExpression数组:
var lambda = (LambdaExpression) lambdaFactory.Invoke(
null,
new object[] {
someBodyExpression,
new ParameterExpression[] { }
}
);这将反映您如何非反射地调用Lambda:
// I'm passing no extra arguments, so an empty array is passed to the "params" parameter
Lambda<T>(someBodyExpression)https://stackoverflow.com/questions/65444177
复制相似问题