如何在C#中使用Java风格的关键字?
在Java中, throws
关键字允许一种方法来声明它不会自己处理exception,而是把它抛给调用方法。
在C#中是否有类似的关键字/属性?
如果没有相同的东西,你怎么能达到同样的效果?
在Java中,您必须处理一个exception,或将该方法标记为可能使用throws
关键字throws
。
C#没有这个关键字或者一个等价的关键字,就像在C#中一样,如果你没有处理一个exception,它就会冒泡,直到被捕获,或者如果没有被捕获,将会终止程序。
如果你想处理它,然后重新抛出你可以做到以下几点:
try { // code that throws an exception } catch(ArgumentNullException ex) { // code that handles the exception throw; }
操作系统询问Java的throws
子句的C#等价物 – 不是throw
关键字。 这在Java中的方法签名中用于指示可以抛出检查的exception。
在C#中,没有直接相当于Java检查的exception。 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... }
以下是我刚刚在bytes.com上提供的一个类似问题的答案:
简短的答案是否定的,在C#中没有检查exception。 语言的devise者在这次采访中讨论了这个决定:
http://www.artima.com/intv/handcuffs.html
你可以得到的最接近的是在你的XML文档中使用标签,并且将NDoc生成的文档分发给你的代码/程序集,这样其他人就可以看到你抛出了哪些exception(这正是MS在MSDN文档中所做的)。 你不能依靠编译器来告诉你有关未处理的exception,但是,像你可能习惯在Java中。
是的,这是一个古老的线程,但是我经常发现旧线程,当我search答案,所以我想我会添加一些有用的东西,我已经find。
如果您使用的是Visual Studio 2012,则可以使用内置工具来使IDE级别与“抛出”等效。
如果您使用XML文档注释 (如上所述),则可以使用<exception>标记来指定方法或类引发的exception的types,以及有关何时或为什么抛出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); }
其实没有在C#中检查exception可以被认为是好事或坏事。
我自己认为这是一个很好的解决scheme,因为检查exception提供了以下问题:
- 技术例外泄漏到业务/域层,因为您无法在低级别正确处理它们。
- 他们属于方法签名,并不总是与APIdevise很好。
因为在大多数更大的应用程序中,您经常会在检查时看到以下模式发生exception:
try { // Some Code } catch(SomeException ex){ throw new RuntimeException(ex); }
这基本上意味着模拟C#/。NET处理所有exception的方式。
.Net CodeContract EnsuresOnThrow<>
和java throws
描述符之间有一些短暂的相似之处,它们都可以向调用者发出信号,作为可以从函数或方法中引发的exception的types,虽然也有主要的区别2:
-
EnsuresOnThrow<>
不仅仅是指出哪些exception可以被抛出,而且还规定了它们被保证抛出的条件 – 如果exception条件不是微不足道的,这在被调用的方法中可能是非常繁琐的代码。 Javathrows
提供了哪些exception可能被抛出的指示(例如IMO在.Net中的焦点在合同certificatethrow
的方法内,而在Java中焦点转移到调用者以确认exception的可能性)。 - .net CC不区分Java的Checked和Uncheckedexception,虽然CC手册第2.2.2节提到
“仅在调用者期望作为API一部分的exception中使用特殊的后置条件”
- 在.Net中,调用者可以确定是否对exception做任何事情(例如通过禁用合同)。 在Java中,调用者必须执行某些操作 ,即使它在其接口上添加了相同的exception。
代码合同手册在这里
你在问这个:
重新抛出一个例外
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 }
在经历了大部分的答案后,我想补充一些想法。
-
依靠XML文档评论和期待别人依靠是一个不好的select。 我遇到的大多数C#代码都没有logging与XML文档注释完全一致的方法。 然后还有一个更大的问题是,如果没有在C#中检查exception,你怎么能logging你的方法抛出的所有exception,以便API用户知道如何单独处理它们? 请记住,你只知道在你的实现中使用throw关键字抛出的那些关键字。 你在方法实现中使用的API也可能会抛出你不知道的exception,因为它们可能没有被logging下来,而且你没有在你的实现中处理它们,所以它们会面对你的调用者方法。 换句话说,这些XML文档注释不能替代检查的exception。
-
Andreas在答复中将Anders Hejlsberg的采访与C#devise团队为什么决定不检查exception的答案挂钩。 在这次采访中,对原始问题的最终回应是隐藏的:
程序员通过编写try finally来保护他们的代码,所以如果发生exception,他们会正确地退出,但是他们实际上并不想处理这些exception。
换句话说,没有人应该对某个特定的API可以预期什么样的exception感兴趣,因为你总是要把它们全部都捕捉到。 如果你真的想关心特定的exception,如何处理它们取决于你,而不是像Java那样定义方法签名的throws关键字,强制对API用户进行特殊的exception处理。
–
我个人在这里被撕裂。 我同意安德斯所说的检查exception不会解决问题而不会增加新的,不同的问题。 就像使用XML文档注释一样,我很less看到C#代码中的所有内容都被封装在finally块中。 这感觉对我来说这确实是你唯一的select,而且这似乎是一个很好的做法。