【问题标题】:Asking a Generic Method to Throw Specific Exception Type on FAIL要求通用方法在 FAIL 上抛出特定的异常类型
【发布时间】:2008-09-03 10:08:11
【问题描述】:

好吧,我知道我用这个完全会看起来像个白痴,但我的大脑今天早上只是没有开始运转。

我想要一个方法,我可以说“如果它变坏了,就返回这种类型的异常”,对吧?

例如,类似(这不起作用):

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = new Exception(message);
        return ex;
    }

现在让我感到困惑的是,由于 where 子句,我们知道泛型类型将属于异常类型。但是,代码失败了,因为我们不能将 Exception 隐式转换为 ExType。我们也不能显式转换,比如:

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = (ExType)(new Exception(message));
        return ex;
    }

因为那也失败了..所以这种事情可能吗?我有一种强烈的感觉,它会很简单,但我和老头子度过了艰难的一天,所以切我有些懈怠:P


更新

感谢大家的回复,看来不是我是一个完全的白痴! ;)

好的,所以VegardSam 让我可以实例化正确的类型,但显然卡住了,因为 message 参数在实例化后是只读的。

Matt 他的回答一针见血,我已经对此进行了测试,一切正常。下面是示例代码:

    static ExType TestException<ExType>(string message) where ExType:Exception, new ()
    {
        ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
        return ex;
    }

甜! :)

谢谢大家!

【问题讨论】:

  • 坦率地说,我认为以这种方式编写一个方法(“如果它变坏,返回这种类型的异常”)可能被证明是太有问题的 wrt 边缘情况(见下面我的 cmets re. 异常类型,其中message不是第一个字符串arg)并且还具有(in)灵活性。回覆。后者,您可能想要设置的不仅仅是异常的消息,或者使用一些仅由调用者持有的值/变量。也许在许多情况下,可以回调以引发异常的 Action 委托可能更合适?

标签: c# generics exception


【解决方案1】:

你几乎可以这样做:

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 语句中保留我的答案。

【讨论】:

  • 这假定异常类型具有签名public ExceptionType (string message); 的构造函数重载。这通常是,但并非总是如此。一个例外是System.ArgumentOutOfRangeException。它的构造函数的第一个字符串参数是paramName 而不是message。这很烦人。
  • System.ArgumentNullException 也有构造函数public ArgumentNullException (string paramName);
【解决方案2】:

解决方案的唯一问题是可以创建一个 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();
    }
}

【讨论】:

    【解决方案3】:

    我一直在实例化我想抛出的异常类型,如下所示:

    if (ItemNameIsValid(ItemName, out errorMessage))
        throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
    if (null == MyArgument)
        throw new ArgumentNullException("MyArgument is null");
    

    【讨论】:

      【解决方案4】:

      您是否尝试过:

      static T TestException<Exception>(string message)
      {}
      

      因为我觉得没有必要加入通用约束,因为所有可抛出的异常必须从 System.Exception 继承。

      请记住,泛型确实接受继承的类型。

      【讨论】:

        【解决方案5】:

        我认为所有异常都应该有一个无参数的构造函数,并且具有Message 属性,所以以下应该可以工作:

        static ExType TestException<ExType>(string message) where ExType:Exception
        {
            ExType ex = new ExType();
            ex.Message = message;
            return ex;
        }
        

        编辑:好的,Message 是只读的,所以你必须希望类实现 Exception(string) 构造函数。

        static ExType TestException<ExType>(string message) where ExType:Exception
        {
            return new ExType(message);
        }
        

        【讨论】:

        • 您的第二个代码 sn-p 也无法编译。没有办法为构造函数指定一个需要一个字符串参数的泛型类型约束。
        猜你喜欢
        • 1970-01-01
        • 2015-12-17
        • 2012-11-22
        • 2013-05-17
        • 1970-01-01
        • 1970-01-01
        • 2010-11-22
        • 2014-05-15
        • 1970-01-01
        相关资源
        最近更新 更多