簡體   English   中英

帶有參數的方法的簽名是什么?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM