FAIL 時に特定の例外タイプをスローするように汎用メソッドを要求する

StackOverflow https://stackoverflow.com/questions/41397

  •  09-06-2019
  •  | 
  •  

質問

そう、これをやると完全にバカに見えるのは分かっているけど、私の脳は ない 今朝からギアが入りました。

「うまくいかなかったら、このタイプの例外で戻ってきます」と言えるメソッドが欲しいですよね。

たとえば、次のようなものです (そしてこれは機能しません):

    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);
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top