110

在 Java 中,throws关键字允许方法声明它不会自行处理异常,而是将其扔给调用方法。

C# 中是否有类似的关键字/属性?

如果没有等价物,您如何实现相同(或相似)的效果?

4

10 回答 10

128

该操作询问的是 Javathrows子句的 C# 等价物- 而不是throw关键字。这在 Java 中的方法签名中使用,以指示可以抛出已检查的异常。

在 C# 中,没有直接等效于 Java 检查异常。C# 没有等效的方法签名子句。

// Java - need to have throws clause if IOException not handled
public void readFile() throws java.io.IOException {
  ...not explicitly handling java.io.IOException...
}

翻译成

// C# - no equivalent of throws clause exceptions are unchecked
public void ReadFile() 
{
  ...not explicitly handling System.IO.IOException...
}
于 2010-08-12T12:07:58.353 回答
90

在 Java 中,您必须要么处理异常,要么使用throws关键字将方法标记为可能抛出异常的方法。

C# 没有 this 关键字或等效的关键字,如在 C# 中,如果您不处理异常,它将冒泡,直到被捕获或如果没有被捕获,它将终止程序。

如果您想处理它然后重新抛出您可以执行以下操作:

try
{
  // code that throws an exception
}
catch(ArgumentNullException ex)
{
  // code that handles the exception
  throw;
}
于 2010-08-12T07:17:06.143 回答
47

Yes this is an old thread, however I frequently find old threads when I am googling answers so I figured I would add something useful that I have found.

If you are using Visual Studio 2012 there is a built in tool that can be used to allow for an IDE level "throws" equivalent.

If you use XML Documentation Comments, as mentioned above, then you can use the <exception> tag to specify the type of exception thrown by the method or class as well as information on when or why it is thrown.

example:

    /// <summary>This method throws an exception.</summary>
    /// <param name="myPath">A path to a directory that will be zipped.</param>
    /// <exception cref="IOException">This exception is thrown if the archive already exists</exception>
    public void FooThrowsAnException (string myPath)
    {
        // This will throw an IO exception
        ZipFile.CreateFromDirectory(myPath);
    }
于 2013-07-23T12:37:19.733 回答
20

这是我刚刚在bytes.com上找到的类似问题的答案:

最简洁的答案是不。C# 中没有检查异常。该语言的设计者在这次采访中讨论了这个决定:

http://www.artima.com/intv/handcuffs.html

您可以获得的最接近的方法是使用 XML 文档中的标签,并将 NDoc 生成的文档与您的代码/程序集一起分发,以便其他人可以看到您抛出的异常(这正是 MS 在 MSDN 文档中所做的)。但是,您不能依赖编译器来告诉您未处理的异常,就像您在 java 中习惯的那样。

于 2010-08-12T07:24:06.293 回答
8

在浏览了这里的大部分答案之后,我想补充一些想法。

  1. 依赖 XML 文档注释并期望其他人依赖是一个糟糕的选择。我遇到的大多数 C# 代码都没有完全和一致地记录方法与 XML 文档注释。然后还有一个更大的问题,在 C# 中如果没有检查异常,您如何记录您的方法抛出的所有异常,以便您的 API 用户知道如何单独处理它们?请记住,您只知道在您的实现中使用 throw 关键字抛出的那些。您在方法实现中使用的 API 也可能会引发您不知道的异常,因为它们可能没有记录在案并且您没有在实现中处理它们,因此它们会在您的调用者面前爆炸方法。换句话说,

  2. Andreas 在此处的答案中链接了对 Anders Hejlsberg 的采访,解释了为什么 C# 设计团队决定反对检查异常。对原始问题的最终回答隐藏在该采访中:

程序员通过在任何地方都编写 try finally 来保护他们的代码,因此如果发生异常,他们会正确退出,但他们实际上对处理异常并不感兴趣。

换句话说,没有人应该对特定 API 会出现什么样的异常感兴趣,因为您总是会在任何地方捕获所有异常。如果你想真正关心特定的异常,如何处理它们取决于你,而不是有人用 Java throws 关键字定义方法签名,强制 API 用户处理特定的异常。

--

就个人而言,我在这里被撕裂了。我同意 Anders 的观​​点,即检查异常并不能在不添加新的不同问题的情况下解决问题。就像 XML 文档注释一样,我很少看到 C# 代码的所有内容都包含在 try finally 块中。尽管这确实是您唯一的选择,但在我看来,这似乎是一种很好的做法。

于 2017-05-24T22:39:17.923 回答
3

实际上,在 C# 中没有检查异常可以被认为是一件好事或坏事。

我自己认为这是一个很好的解决方案,因为检查异常会为您提供以下问题:

  1. 技术异常泄漏到业务/域层,因为您无法在低级别正确处理它们。
  2. 它们属于方法签名,并不总是与 API 设计配合得很好。

因此,在大多数大型应用程序中,当检查异常时,您会经常看到以下模式:

try {
    // Some Code
} catch(SomeException ex){
    throw new RuntimeException(ex);
}

这实质上意味着模拟 C#/.NET 处理所有异常的方式。

于 2010-08-12T07:50:49.917 回答
3

你在问这个:

重新抛出异常

public void Method()
{
  try
  {
      int x = 0;
      int sum = 100/x;
  }
  catch(DivideByZeroException e)
  {
      throw;
  }
}

或者

static void Main() 
    {
        string s = null;

        if (s == null) 
        {
            throw new ArgumentNullException();
        }

        Console.Write("The string s is null"); // not executed
    }
于 2010-08-12T07:18:01.960 回答
2

EnsuresOnThrow<>.Net CodeContract和 java描述符之间有一些短暂的相似之处throws,因为两者都可以向调用者发出可以从函数或方法引发的异常类型的信号,尽管两者之间也存在重大差异:

  • EnsuresOnThrow<>不仅仅是说明可以抛出哪些异常,还规定了保证抛出它们的条件 - 如果异常条件不容易识别,这可能是被调用方法中相当繁琐的代码。Javathrows提供了可以引发哪些异常的指示(即,IMO .Net 中的重点是在合同中证明 .Net 的方法内部throw,而在 Java 中,焦点转移到调用者以确认异常的可能性)。
  • .Net CC 没有区分 Java 具有的Checked 和 Unchecked异常,尽管 CC 手册第 2.2.2 节确实提到了

“仅对调用者应该期望作为 API 一部分的那些异常使用异常后置条件”

  • 在.Net 中,调用者可以确定是否对异常进行任何处理(例如,通过禁用合同)。在 Java 中,调用者必须做某事,即使它throws在其接口上为相同的异常添加了一个。

代码合同手册在这里

于 2013-09-18T10:07:04.403 回答
1

如果 c# 方法的目的是只抛出异常(如 js 返回类型所说),我建议只返回该异常。请参见下面的示例:

    public EntityNotFoundException GetEntityNotFoundException(Type entityType, object id)
    {
        return new EntityNotFoundException($"The object '{entityType.Name}' with given id '{id}' not found.");
    }

    public TEntity GetEntity<TEntity>(string id)
    {
        var entity = session.Get<TEntity>(id);
        if (entity == null)
            throw GetEntityNotFoundException(typeof(TEntity), id);
        return entity;
    }

于 2019-11-13T10:54:40.907 回答
-1

对于那些想知道的人,您甚至不需要定义捕获的内容即可将其传递给下一个方法。如果您希望在一个主线程中处理所有错误,您可以捕获所有内容并将其传递,如下所示:

try {
    //your code here
}
catch {
    //this will throw any exceptions caught by this try/catch
    throw;
}
于 2020-01-17T09:09:21.607 回答