FAIL 時に特定の例外タイプをスローするように汎用メソッドを要求する
質問
そう、これをやると完全にバカに見えるのは分かっているけど、私の脳は ない 今朝からギアが入りました。
「うまくいかなかったら、このタイプの例外で戻ってきます」と言えるメソッドが欲しいですよね。
たとえば、次のようなものです (そしてこれは機能しません):
static ExType TestException<ExType>(string message) where ExType:Exception
{
Exception ex1 = new Exception();
ExType ex = new Exception(message);
return ex;
}
さて、私を混乱させているのは、私たちが 知る ジェネリック型は、次の理由により例外型になることを示します。 どこ 句。ただし、暗黙的にキャストできないため、コードは失敗します。 例外 に ExType. 。次のように明示的に変換することもできません。
static ExType TestException<ExType>(string message) where ExType:Exception
{
Exception ex1 = new Exception();
ExType ex = (ExType)(new Exception(message));
return ex;
}
それも失敗するので…それで このようなことは可能ですか? 本当に簡単になると強く感じていますが、古いノギンで大変な一日を過ごしているので、少し休んでください :P
アップデート
皆さん、ご返信ありがとうございます。どうやら私ではなかったようです。 完了 ばか!;)
はい、それでは ベガード そして サム 正しい型をインスタンス化できるところまでは進めましたが、その後明らかに行き詰まってしまいました。 メッセージ param はインスタンス化後は読み取り専用です。
マット 彼の反応は見事に的中しました。私はこれをテストしましたが、すべてうまくいきました。コード例は次のとおりです。
static ExType TestException<ExType>(string message) where ExType:Exception, new ()
{
ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
return ex;
}
甘い!:)
みんなありがとう!
解決
ほぼ次のように行うことができます。
static void TestException<E>(string message) where E : Exception, new()
{
var e = new E();
e.Message = message;
throw e;
}
ただし、Exception.Message は読み取り専用であるため、コンパイルできません。コンストラクターに渡すことによってのみ割り当てることができ、既定のコンストラクター以外のものでジェネリック型を制約する方法はありません。
次のように、メッセージ パラメーターを持つカスタム例外タイプを「新規作成」するには、リフレクション (Activator.CreateInstance) を使用する必要があると思います。
static void TestException<E>(string message) where E : Exception
{
throw Activator.CreateInstance(typeof(E), message) as E;
}
編集 おっと、あなたがそうしたいと思っていることに今気づきました 戻る 例外をスローするのではありません。同じ原則が適用されるため、throw ステートメントについては回答をそのままにしておきます。
他のヒント
この解決策の唯一の問題は、単一の文字列パラメーターを持つコンストラクターを実装しない Exception のサブクラスを作成できるため、MethodMissingException がスローされる可能性があることです。
static void TestException<E>(string message) where E : Exception, new()
{
try
{
return Activator.CreateInstance(typeof(E), message) as E;
}
catch(MissingMethodException ex)
{
return new E();
}
}
次のように、スローしたい例外のタイプをインラインでインスタンス化しています。
if (ItemNameIsValid(ItemName, out errorMessage))
throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
if (null == MyArgument)
throw new ArgumentNullException("MyArgument is null");
代わりに次のことを試してみましたか?
static T TestException<Exception>(string message)
{}
すべてのスロー可能な例外のように、汎用制約を入れる必要はないと感じているためです。 しなければならない とにかく System.Exception から継承します。
ジェネリックは継承型を受け入れることに注意してください。
すべての例外にはパラメーターのないコンストラクターが必要であり、 Message
プロパティなので、次のように機能するはずです。
static ExType TestException<ExType>(string message) where ExType:Exception
{
ExType ex = new ExType();
ex.Message = message;
return ex;
}
編集:OK、Message は読み取り専用なので、代わりにクラスが Exception(string) コンストラクターを実装することを期待する必要があります。
static ExType TestException<ExType>(string message) where ExType:Exception
{
return new ExType(message);
}