C# try-catch-else

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1177438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:06:33  来源:igfitidea点击:

C# try-catch-else

c#exception-handling

提问by Martin Sherburn

One thing that has bugged me with exception handling coming from Python to C# is that in C# there doesn't appear to be any way of specifying an else clause. For example, in Python I could write something like this (Note, this is just an example. I'm not asking what is the best way to read a file):

从 Python 到 C# 的异常处理让我感到困扰的一件事是,在 C# 中似乎没有任何指定 else 子句的方法。例如,在 Python 中我可以写这样的东西(注意,这只是一个例子。我不是问什么是读取文件的最佳方式):

try
{
    reader = new StreamReader(path);
}
catch (Exception)
{
    // Uh oh something went wrong with opening the file for reading
}
else
{
    string line = reader.ReadLine();
    char character = line[30];
}

From what I have seen in most C# code people would just write the following:

从我在大多数 C# 代码中看到的情况来看,人们只会编写以下内容:

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (Exception)
{
    // Uh oh something went wrong, but where?
}

The trouble with this is that I don't want to catch out of range exception coming from the fact that the first line in the file may not contain more than 30 characters. I only want to catch exceptions relating to the reading of the file stream. Is there any similar construct I can use in C# to achieve the same thing?

这样做的问题是,我不想捕获超出范围的异常,因为文件中的第一行可能不包含超过 30 个字符。我只想捕获与读取文件流有关的异常。我可以在 C# 中使用任何类似的构造来实现相同的目标吗?

回答by Henk Holterman

Catch a specific class of exceptions

捕获特定类别的异常

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (IOException ex)
{
    // Uh oh something went wrong with I/O
}
catch (Exception ex)
{
    // Uh oh something else went wrong
    throw; // unless you're very sure what you're doing here.
}

The second catch is optional, of course. And since you don't know what happened, swallowing this most general exception is very dangerous.

当然,第二个捕获是可选的。而且由于你不知道发生了什么,吞下这个最普遍的异常是非常危险的。

回答by Adrian Godong

You can do this:

你可以这样做:

try
{
    reader = new StreamReader(path);
}
catch (Exception)
{
    // Uh oh something went wrong with opening the file for reading
}

string line = reader.ReadLine();
char character = line[30];

But of course, you will have to set readerinto a correct state or returnout of the method.

但是当然,您将不得不设置reader为正确的状态或return退出该方法。

回答by John Saunders

Exceptions are used differently in .NET; they are for exceptional conditions only.

.NET 中异常的使用方式不同;它们仅适用于特殊情况。

In fact, you should not catch an exception unless you know what it means, and can actually dosomething about it.

事实上,除非您知道异常的含义,并且实际上可以对此做些什么,否则您不应该捕获异常。

回答by Michael A. McCloskey

You can have multiple catch clauses, each specific to the type of exception you wish to catch. So, if you only want to catch IOExceptions, then you could change your catch clause to this:

您可以有多个 catch 子句,每个子句都特定于您希望捕获的异常类型。因此,如果您只想捕获 IOExceptions,那么您可以将 catch 子句更改为:

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (IOException)
{    
}

Anything other than an IOException would then propagate up the call stack. If you want to also handle other exceptions, then you can add multiple exception clauses, but you must ensure they are added in most specific to most generic order. For example:

除了 IOException 之外的任何东西都会向上传播调用堆栈。如果您还想处理其他异常,则可以添加多个异常子句,但必须确保以最具体到最通用的顺序添加它们。例如:

try
{
    reader = new StreamReader(path);
    string line = reader.ReadLine();
    char character = line[30];
}
catch (IOException)
{    
}
catch (Exception)
{
}

回答by jason

Catch more specific exceptions.

捕捉更具体的异常。

try {
   reader = new StreamReader(path);
   string line = reader.ReadLine();
   char character = line[30];
}
catch(FileNotFoundException e) {
   // thrown by StreamReader constructor
}
catch(DirectoryNotFoundException e) {
   // thrown by StreamReader constructor
}
catch(IOException e) {
   // some other fatal IO error occured
}

Further, in general, handle the most specific exception possible and avoid handling the base System.Exception.

此外,一般来说,尽可能处理最具体的异常并避免处理 base System.Exception

回答by Steve Gilham

More idiomatically, you would employ the usingstatement to separate the file-open operation from the work done on the data it contains (and include automatic clean-up on exit)

更惯用的是,您将使用该using语句将文件打开操作与其包含的数据所做的工作分开(并包括退出时的自动清理)

try {
  using (reader = new StreamReader(path))
  {
    DoSomethingWith(reader);
  }
} 
catch(IOException ex)
{
  // Log ex here
}

It is also best to avoid catching every possible exception -- like the ones telling you that the runtime is about to expire.

最好避免捕获所有可能的异常——比如那些告诉您运行时即将到期的异常。

回答by David

You can nest your try statements, too

你也可以嵌套你的 try 语句

回答by Christian Birkl

Is there any similar construct I can use in C# to acheive the same thing?

我可以在 C# 中使用任何类似的构造来实现相同的目标吗?

No.

不。

Wrap your index accessor with an "if" statement which is the best solution in your case in case of performance and readability.

用“if”语句包装您的索引访问器,这是性能和可读性方面的最佳解决方案。

if (line.length > 30) {
   char character = line [30];
} 

回答by Johan Kullbom

You could write it like:

你可以这样写:

bool success = false;
try {
    reader = new StreamReader(path);
    success = true;
}
catch(Exception) {
    // Uh oh something went wrong with opening the file for reading
}
finally {
    if(success) {
        string line = reader.ReadLine();    
        char character = line[30];
    }
}   

回答by Martin Liversage

I have taken the liberty to transform your code a bit to demonstrate a few important points.

我冒昧地对您的代码进行了一些转换,以展示一些重要的观点。

The usingconstruct is used to open the file. If an exception is thrown you will have to remember to close the file even if you don't catch the exception. This can be done using a try { } catch () { } finally { }construct, but the usingdirective is much better for this. It guarantees that when the scope of the usingblock ends the variable created inside will be disposed. For a file it means it will be closed.

using构造用于打开文件。如果抛出异常,即使您没有捕获异常,您也必须记住关闭文件。这可以使用try { } catch () { } finally { }构造来完成,但using指令在这方面要好得多。它保证当using块的作用域结束时,内部创建的变量将被释放。对于文件,这意味着它将被关闭。

By studying the documentation for the StreamReaderconstructor and ReadLinemethod you can see which exceptions you may expect to be thrown. You can then catch those you finde appropriate. Note that the documented list of exceptions not always is complete.

通过研究StreamReader构造函数和ReadLine方法的文档,您可以了解可能会抛出哪些异常。然后你可以抓住那些你认为合适的人。请注意,记录在案的例外列表并不总是完整的。

// May throw FileNotFoundException, DirectoryNotFoundException,
// IOException and more.
try {
  using (StreamReader streamReader = new StreamReader(path)) {
    try {
      String line;
      // May throw IOException.
      while ((line = streamReader.ReadLine()) != null) {
        // May throw IndexOutOfRangeException.
        Char c = line[30];
        Console.WriteLine(c);
      }
    }
    catch (IOException ex) {
      Console.WriteLine("Error reading file: " + ex.Message);
    }
  }
}
catch (FileNotFoundException ex) {
  Console.WriteLine("File does not exists: " + ex.Message);
}
catch (DirectoryNotFoundException ex) {
  Console.WriteLine("Invalid path: " + ex.Message);
}
catch (IOException ex) {
  Console.WriteLine("Error reading file: " + ex.Message);
}