共用方式為


反映叫用 API 例外狀況的變更

呼叫反映叫用 API 變更時擲回的例外狀況。

先前的行為

  • 先前,藉傳址傳回值的叫用方式傳回 null 時,會擲回 NullReferenceException

  • 針對建構函式,則擲回下列例外狀況:

  • 在沒有 ref 修飾元的情況針對類似 byref 的參數傳遞 null 時 (也就是以值傳遞),沒有擲回例外狀況,且執行時間會以預設值取代 Null 值。

新的行為

從 .NET 7 開始:

導入的版本

.NET 7

中斷性變更的類型

這項變更會影響二進位相容性

變更原因

擲回 TargetInvocationException 而不是原始例外狀況,可讓體驗更一致。 這將傳入參數驗證所造成的例外狀況 (這些參數不會與 TargetInvocationException 一起包裝),與因實作目標方法而擲回的例外狀況 (已包裝) 進行適當地分層。 一致的規則可在 CLR 和 Invoke API 的不同實作之間提供更一致的體驗。

類似 byref 的類型傳遞至 Invoke() API 時,擲回 NotSupportedException 的變更會修正原始實作的監督,而不會擲回。 原始實作給人 Invoke() API 所支援 ref struct 類型的印象,但事實並非如此。 由於目前的 Invoke() API 使用 System.Object 作為參數類型,且 ref struct 類型無法以 boxed 處理為 System.Object,因此是不支援的案例。

如果您在呼叫 Invoke() 時未使用 BindingFlags.DoNotWrapExceptions,而且針對 TargetInvocationException 以外的例外狀況,您有 Invoke() API 周圍的陳述式 catch,請考慮變更或移除這些 catch 陳述式。 其他例外狀況將不會再因叫用而擲回。 不過,如果您從嘗試叫用目標方法之前發生的引數驗證攔截例外狀況,您應該保留這些 catch 陳述式。 在嘗試叫用之前驗證的引數會擲回,而每有與 TargetInvocationException 一同包裝,且不會變更語意。

請考慮使用 BindingFlags.DoNotWrapExceptions,這樣才永遠不會擲回 TargetInvocationException。 在此情況下,原始例外狀況不會由 TargetInvocationException 包裝。 大部分情況下,不包裝例外狀況可改善診斷實際問題的機會,因為並非所有例外狀況報告工具都會顯示內部例外狀況。 此外,使用 BindingFlags.DoNotWrapExceptions 將會擲回與直接呼叫方法相同的例外狀況(不需要反映)。 多數情況下這是理想的做法,因為使用反映的選擇可以是任意的,或是不需要呈現給呼叫端的實作詳細資料。

少數情況下您必須透過反映將預設值傳遞至方法,其中包含傳遞「by value」的類似 byref 參數的方法,您可以新增省略參數的包裝函式方法,並使用該參數的預設值呼叫目標方法。

受影響的 API