反映APIを呼び出す際に発生する例外が変更されました。
以前の動作
以前は、参照渡しの値を返すメソッドが呼び出されて
nullが返されると、NullReferenceException がスローされました。コンストラクターの場合、次の例外がスローされました。
- OutOfMemoryExceptionを含む一時的な例外。
- 配列の長さパラメーターに負の値が渡されたときの OverflowException 。
null修飾子 (つまり、値渡し) なしで byref のようなパラメーターに対してrefが渡された場合、例外はスローされず、ランタイムは null 値の既定値を置き換えました。
新しい動作
.NET 7 以降:
発生元の例外 (NullReferenceExceptionで説明したOutOfMemoryExceptionとを含む) をスローする代わりに、最初のTargetInvocationException パラメーターが検証された後、すべてのケースで
Invoke()がスローされます。 内部例外には、発生元の例外が含まれています。NotSupportedExceptionは、パラメーターが "by value" として宣言されているときに
nullパラメーターに対してが渡されるときにスローされます (つまり、ref修飾子がありません)。 パラメーターが参照渡しされる (つまり、ref修飾子を持つ) 関連したケースでは、以前の動作と新しい動作は同じで、NotSupportedException がスローされます。
導入されたバージョン
.NET 7
破壊的変更の種類
この変更は 、バイナリの互換性に影響する可能性があります。
変更の理由
元の例外の代わりに TargetInvocationException をスローすることで、エクスペリエンスがより一貫したものになります。 受信パラメーター ( TargetInvocationException でラップされていない) の検証によって発生する例外と、ターゲット メソッド (ラップされる) の実装によってスローされた例外を適切に階層化します。 一貫性のあるルールにより、CLR と Invoke API のさまざまな実装で、より一貫性のあるエクスペリエンスが提供されます。
NotSupportedExceptionが API に渡されたときに Invoke() をスローする変更では、(スローしなかった) 元の実装の見落としが修正されています。 元の実装では、ref struct 型が実際にはサポートされていないにもかかわらず、Invoke() API がそれらをサポートしているかのような印象を与えていました。 現在の Invoke() API ではパラメーター型に System.Object が使用されており、 ref struct 型を System.Objectボックス化できないため、サポートされていないシナリオです。
推奨されるアクション
BindingFlags.DoNotWrapExceptionsを呼び出すときにInvoke()を使用せず、catch以外の例外に対してInvoke() API の周囲にTargetInvocationExceptionステートメントがある場合は、これらのcatchステートメントを変更または削除することを検討してください。 その他の例外は、呼び出しの結果としてスローされなくなります。 ただし、ターゲット メソッドを呼び出す前に発生する引数の検証から例外をキャッチする場合は、それらの catch ステートメントを保持する必要があります。 呼び出しを試みる前に検証された無効な引数は、 TargetInvocationException でラップされずにスローされ、セマンティクスは変更されませんでした。
BindingFlags.DoNotWrapExceptions がスローされないように、TargetInvocationException を使うことを検討してください。 この場合、発生元の例外は TargetInvocationExceptionによってラップされません。 ほとんどの場合、例外をラップしないと、すべての例外レポート ツールで内部例外が表示されるわけではないため、実際の問題を診断する可能性が向上します。 さらに、BindingFlags.DoNotWrapExceptions を使用すると、メソッドを直接呼び出すときと同じ例外がスローされます (リフレクションなし)。 リフレクションを使用するかどうかの選択は任意か、または呼び出し元に表示する必要のない実装の詳細であるため、ほとんどの場合、これは望ましいことです。
まれに、"by value" で渡される byref のような パラメーターを含むリフレクションを介してメソッドに既定値を渡す必要がある場合は、パラメーターを省略し、そのパラメーターの既定値を使用してターゲット メソッドを呼び出すラッパー メソッドを追加できます。
影響を受ける API
- System.Reflection.MethodBase.Invoke(Object, Object[])
- System.Reflection.MethodBase.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.ConstructorInfo.Invoke(Object[])
- System.Reflection.ConstructorInfo.Invoke(BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.PropertyInfo.GetValue(Object)
- System.Reflection.PropertyInfo.GetValue(Object, Object[])
- System.Reflection.PropertyInfo.GetValue(Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.PropertyInfo.SetValue(Object, Object)
- System.Reflection.PropertyInfo.SetValue(Object, Object, Object[])
- System.Reflection.PropertyInfo.SetValue(Object, Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.Emit.DynamicMethod.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Activator.CreateInstance(Type, Object[])
- System.Activator.CreateInstance(Type, Object[], Object[])
- System.Activator.CreateInstance(Type, BindingFlags, Binder, Object[], CultureInfo)
- System.Activator.CreateInstance(Type, BindingFlags, Binder, Object[], CultureInfo, Object[])
- System.Activator.CreateInstance(String, String, Boolean, BindingFlags, Binder, Object[], CultureInfo, Object[])
.NET