【问题标题】:Catching exception types given as type parameters in C# 2.0在 C# 2.0 中捕获作为类型参数给出的异常类型
【发布时间】:2009-11-18 14:10:34
【问题描述】:

在下面的方法中,第一个 catch 块永远不会运行,即使抛出了 ExceptionType 类型的异常:

    /// <summary>
    /// asserts that running the command given throws an exception.
    /// </summary>
    public static void Throws<ExceptionType>(ICommand cmd)
        where ExceptionType : Exception
    {
        // Strangely, using 2 catch blocks on the code below makes the first catch block do nothing.
        try
        {
            try
            {
                cmd.Execute();
            }
            catch (ExceptionType)
            {
                return;
            }
        }
        catch (Exception f)
        {
            throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ".  Expected type was " + typeof(ExceptionType).Name + ".");
        }

        throw new AssertionException(cmd.ToString() + " failed to throw a " + typeof(ExceptionType).Name + ".");
    }

如以下测试所示:

    [Test]
    public void Test_Throws_CatchesSpecifiedException()
    {
        AssertThat.Throws<AssertionException>(
            new FailureCommand()
        );
    }

使用以下类:

class FailureCommand : ICommand
{
    public object Execute()
    {
        Assert.Fail();
        return null;    // never reached.
    }

    public override string ToString()
    {
        return "FailureCommand";
    }
}

在 NUnit 中给出以下输出:

TestUtil.Tests.AssertThatTests.Test_Throws_CatchesSpecifiedException: FailureCommand 引发了 NUnit.Framework.AssertionException 类型的异常。预期的类型是 AssertionException。

我还尝试将 2 个 catch 块用于 1 个 try 块(而不是在外部 try 中嵌套 try/catch),但得到了相同的结果。

关于如何在一个捕获块中捕获指定为类型参数的异常,但在另一个捕获块中捕获所有其他异常的任何想法?

【问题讨论】:

    标签: c# .net generics exception


    【解决方案1】:

    在这个测试中对我来说很好:

    using System;
    using System.IO;
    
    class Test
    {
        static void Main()
        {
            Throws<ArgumentNullException>(() => File.OpenText(null));
        }
    
        public static void Throws<ExceptionType>(Action cmd)
            where ExceptionType : Exception
        {
            try
            {
                try
                {
                    cmd();
                }
                catch (ExceptionType)
                {
                    Console.WriteLine("Caught!");
                    return;
                }
            }
            catch (Exception f)
            {
                Console.WriteLine("Threw an exception of type " + f.GetType() 
                    + ".  Expected type was " + typeof(ExceptionType) + ".");
            }
    
            Console.WriteLine("No exception thrown");
        }
    }
    

    您有多确定这两个AssertionException 异常是相同的?它们肯定在同一个命名空间中吗(打印typeof(ExceptionType) 而不仅仅是 Name 属性)?他们来自同一个大会吗?由于多个测试框架版本并存,我不会感到奇怪...

    尝试使用AssertionException 以外的例外,让生活更简单。

    【讨论】:

      【解决方案2】:
      【解决方案3】:

      我没有调试此代码或查看它太久,但可能是您的第一个“return”语句导致代码暂停并离开该方法。因此,异常是“捕获”或“已处理”(无论您怎么看),并且永远不会执行外部 try/catch 块。

      你想这样做吗?

      try        
      {            
          try            
          {                
              cmd.Execute();            
          }            
          catch (ExceptionType)            
          {                
              throw;
          }        
      }        
      catch (Exception f)        
      {            
          throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ".  Expected type was "  + typeof(ExceptionType).Name + ".");        
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-05-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-26
        • 1970-01-01
        • 2015-11-17
        • 2018-01-04
        相关资源
        最近更新 更多