[英]What is the signature of a method with params?
我正要以編程方式綁定Expression.Lambda
(因為未知/可變類型參數),發現如果目標方法使用params
,則反射調用與直接調用有點不同。
首先,在官方文檔中,“簽名”(雖然這更像是 XML-doc):
public static
System.Linq.Expressions.Expression<TDelegate>
Lambda<TDelegate>(
System.Linq.Expressions.Expression body,
params System.Linq.Expressions.ParameterExpression[]? parameters
);
請注意,第二個參數被標記為可選,我們可以編寫Expression.Lambda<T>(...)
。 如果在 Visual Studio 中,你 go 到反匯編聲明列表,你可以看到:
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 Docs 使用?
(可選標記)? params
參數是否真的是可選的,類似於常規選項 arguments,如string Foo(int a = 1); var result = Foo();
string Foo(int a = 1); var result = Foo();
? 或者它只是一個語法糖? 所以這就是為什么我可以在編輯器中直接調用Expression.Lambda<T>(...)
,但是編譯的代碼可以不同(這也與反射系統兼容)。 如果是這樣,這是否意味着該方法總是接收null
值,即使我沒有指定值? 但是,如果一個方法使用params
參數,並且沒有傳遞任何內容,則方法體中的參數是一個有效的數組,其中.Count == 0
,而不是null
。 使用反射傳遞null
是否安全,或者我應該創建一個空的 object 數組?
?
在文檔中表示可為空的引用類型,而不是可選參數。 可空引用類型純粹是“編譯時檢查”的事情,在運行時,它們與常規的舊引用類型沒有什么不同。 :
可空引用類型不是新的 class 類型,而是對現有引用類型的注釋。 編譯器使用這些注釋來幫助您找到代碼中潛在的 null 參考錯誤。 不可空引用類型和可空引用類型之間沒有運行時差異。 編譯器不會為不可為空的引用類型添加任何運行時檢查。 好處在於編譯時分析。 編譯器會生成警告,幫助您查找和修復代碼中潛在的 null 錯誤。 您聲明您的意圖,當您的代碼違反該意圖時,編譯器會警告您。
這解釋了為什么?
當您查看“反匯編聲明列表”時消失。
全部?
告訴您的是,您可以將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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.