在Java中,throws
关键字允许方法声明自己不会处理异常,而是将其扔给调用方法。
C#中是否有类似的关键字/属性?
如果没有等效项,您如何才能实现相同(或相似)的效果?
Answers:
在Java中,您必须处理异常或将方法标记为可能使用throws
关键字抛出该异常的方法。
C#没有此关键字或与之等效的关键字,如C#中那样,如果不处理异常,它将冒泡,直到被捕获或被捕获为止将终止程序。
如果要处理它,然后重新抛出,则可以执行以下操作:
try
{
// code that throws an exception
}
catch(ArgumentNullException ex)
{
// code that handles the exception
throw;
}
操作员询问的是与Java throws
子句等效的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...
}
是的,这是一个旧线程,但是我在搜索答案时经常发现旧线程,所以我想我会添加一些有用的东西。
如果您使用的是Visual Studio 2012,则有一个内置工具可用于允许等效的IDE级别“抛出”。
如果使用XML文档注释(如上所述),则可以使用<exception>标记指定方法或类引发的异常的类型,以及有关何时或为何引发该异常的信息。
例:
/// <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);
}
throws
可能对运行时毫无意义,除了对开发人员有所帮助。同样,@ mvanella在这里指出的是C#完全相同的方法。我假设您已经知道此“ xml文档”具有更重要的用途。我知道这个线程很旧。
throws
子句中明确指定或由throw
命令抛出,否则Java不会冒出异常。这意味着,如果发生RunTimeException,并且未在发生该事件的相同方法中对其进行处理,则执行将在那里停止。
这是我在bytes.com上发现的类似问题的答案:
最简洁的答案是不。C#中没有检查过的异常。语言的设计师在这次采访中讨论了这个决定:
http://www.artima.com/intv/handcuffs.html
最接近的方法是使用XML文档中的标记,并将NDoc生成的文档与代码/程序集一起分发,以便其他人可以看到您抛出了哪些异常(这正是MS在MSDN文档中所做的)。但是,您不能依赖编译器来告诉您未处理的异常,就像您可能习惯于在Java中那样。
在查看完大多数答案之后,我想补充一些想法。
依靠XML文档注释并希望其他人依赖它是一个糟糕的选择。我遇到的大多数C#代码都没有完全和一致地用XML文档注释来记录方法。还有一个更大的问题,就是在C#中没有检查异常,如何记录方法抛出的所有异常,以使API用户知道如何单独处理所有异常?记住,您只知道在实现中使用throw关键字抛出自己的代码。您在方法实现中使用的API可能还会引发您不知道的异常,因为它们可能没有记录,并且您在实现中没有对其进行处理,因此面对您的调用者,它们会爆炸方法。换一种说法,
Andreas将与Anders Hejlsberg的访谈联系在一起,回答了C#设计团队为何决定不检查异常的答案。对原始问题的最终回答隐藏在该采访中:
程序员通过在各处编写try try来保护代码,因此,如果发生异常,他们将正确退出,但是实际上他们对处理异常并不感兴趣。
换句话说,没有人会对特定API预期会发生什么样的异常感兴趣,因为您总是会无处不在地捕获所有异常。而且,如果您真的要关心特定的异常,则如何处理它们取决于您自己,而不是由像Java throws关键字这样的方法定义方法签名的人,它会强制对API用户进行特定的异常处理。
-
就个人而言,我在这里被撕裂了。我同意安德斯(Anders)的观点,即检查异常不会在不添加新的不同问题的情况下解决问题。就像XML文档注释一样,我很少看到C#代码将所有内容包装在try finally块中。在我看来,尽管这确实是您唯一的选择,但似乎是一种很好的做法。
实际上,没有在C#中检查异常可以被认为是一件好事或坏事。
我自己认为这是一个很好的解决方案,因为检查异常会为您带来以下问题:
因此,在大多数较大的应用程序中,选中的异常发生时,您经常会看到以下模式:
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
}
throw
。通过使用它,堆栈跟踪不会丢失。
.Net CodeContract EnsuresOnThrow<>
和Java throws
描述符之间有一些短暂的相似之处,尽管两者之间也存在很大差异,但两者都可以向调用者发出信号,该异常可以从函数或方法中引发,
EnsuresOnThrow<>
不仅说明了可以抛出哪些异常,还规定了可以保证抛出异常的条件-如果异常条件不容易识别,则在调用方法中这可能是相当繁琐的代码。Java throws
提供了可能引发异常的指示(即IMO,.Net的重点是通过合同来证明throw
,而在Java中,重点转移到了调用方,以确认发生异常的可能性)。“仅将异常后置条件用于调用者应期望作为API一部分的那些例外”
throws
在其接口上为相同的异常添加了。如果c#方法的目的只是抛出一个异常(如js return type所示),我建议只返回该异常。参见下面的示例:
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;
}