如何在 C# 中使用 Java 风格的 throws 关键字?
-
27-09-2019 - |
题
解决方案
在Java中,则必须处理异常或标记方法为一体,可使用throws
关键字把它
C#不具有这个关键字或等效之一,因为在C#,如果不处理异常,它会冒泡,直到捕获或如果没有抓住它将会终止该程序。
如果你想处理它,然后再扔,你可以做到以下几点:
try
{
// code that throws an exception
}
catch(ArgumentNullException ex)
{
// code that handles the exception
throw;
}
其他提示
操作人员正在询问 C# 相当于 Java 的 throws
条款 - 不是 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...
}
是的,这是一个旧线程,但是当我在谷歌上搜索答案时,我经常找到旧线程,所以我想我会添加一些我发现的有用的东西。
如果您使用的是 Visual Studio 2012,则有一个内置工具可用于允许 IDE 级别的“抛出”等效项。
如果你使用 XML 文档注释, ,如上所述,那么您可以使用 <异常> 标记指定方法或类抛出的异常类型以及有关何时或为何抛出异常的信息。
例子:
/// <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);
}
下面是一个回答类似的问题我刚上的 bytes.com :
简短的回答是否定的,也有在C#没有检查异常。该 语言的设计者讨论在这次采访中这个决定:
http://www.artima.com/intv/handcuffs.html
您可以得到最近的是使用标签在你的XML 文档,并分发与NDoc的生成的文档你 代码/组件,以便其他人可以看到你抛出哪些异常 (这正是MSDN文档中做什么MS)。你不能依靠 编译器给大家介绍一下未处理的异常,但是,像 你可能在Java被用来
在浏览完这里的大部分答案后,我想补充一些想法。
依赖 XML 文档注释并期望其他人依赖是一个糟糕的选择。我遇到的大多数 C# 代码都没有完整地记录方法,并且与 XML 文档注释保持一致。然后还有一个更大的问题,如果 C# 中没有检查异常,您如何记录您的方法抛出的所有异常,以便 API 用户知道如何单独处理它们?请记住,您只知道在实现中使用 throw 关键字自己抛出的那些。您在方法实现中使用的 API 也可能会引发您不知道的异常,因为它们可能没有记录在案,并且您没有在实现中处理它们,因此它们会在您的调用者面前爆炸。方法。换句话说,这些 XML 文档注释不能替代已检查的异常。
Andreas 在此处的答案中链接了对 Anders Hejlsberg 的采访,了解为什么 C# 设计团队决定反对检查异常。对最初问题的最终回答隐藏在采访中:
程序员通过在各处编写 tryfinally 来保护他们的代码,因此如果发生异常,他们会正确退出,但他们实际上对处理异常并不感兴趣。
换句话说,没有人应该对特定 API 会出现什么样的异常感兴趣,因为您总是会在任何地方捕获所有异常。如果您想真正关心特定的异常,那么如何处理它们取决于您,而不是由某人使用 Java throws 关键字定义方法签名,从而强制 API 用户进行特定的异常处理。
--
就我个人而言,我在这里很痛苦。我同意 Anders 的观点,即如果不添加新的不同问题,检查异常并不能解决问题。就像 XML 文档注释一样,我很少看到 C# 代码将所有内容都包含在 try finally 块中。在我看来,这确实是你唯一的选择,而且似乎是一个很好的做法。
实际上,C# 中没有检查异常可以被认为是一件好事,也可以被认为是一件坏事。
我自己认为这是一个很好的解决方案,因为检查异常为您提供了以下问题:
- 技术异常会泄漏到业务/域层,因为您无法在低级别正确处理它们。
- 它们属于方法签名,但并不总是能很好地配合 API 设计。
因此,在大多数较大的应用程序中,当发生检查异常时,您经常会看到以下模式:
try {
// Some Code
} catch(SomeException ex){
throw new RuntimeException(ex);
}
这本质上意味着模拟 C#/.NET 处理所有异常的方式。
您问这个问题:
<强>重新抛出异常强>
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
}
.Net CodeContract 之间有一些短暂的相似之处 EnsuresOnThrow<>
和爪哇 throws
描述符,因为两者都可以向调用者发出可以从函数或方法引发的异常类型的信号,尽管两者之间也存在重大差异:
EnsuresOnThrow<>
不仅仅是说明可以抛出哪些异常,还规定了保证抛出异常的条件 - 如果异常条件不易识别,那么在被调用方法中这可能是相当繁重的代码。爪哇throws
提供可以抛出哪些异常的指示(即IMO .Net 中的重点在于合同证明的方法内部throw
, ,而在 Java 中,焦点转移到调用者以确认异常的可能性)。- .Net CC 不区分 选中与未选中 Java 有例外,尽管 CC 手册第 2.2.2 节确实提到了
“仅适用于呼叫者应作为API一部分的例外情况使用出色的后条件”
- 在 .Net 中,调用者可以确定是否对异常执行任何操作(例如通过禁用合同)。在 Java 中,调用者 必须做某事, ,即使它添加了一个
throws
对于其接口上的相同异常。