Как использовать ключевое слово Java-style throws в C#?


в Java throws ключевое слово позволяет методу объявить, что он не будет обрабатывать исключение самостоятельно, а скорее бросит его в вызывающий метод.

есть ли подобное ключевое слово / атрибут в C#?

если нет эквивалента, как вы можете достичь того же (или аналогичного) эффекта?

8 64

8 ответов:

в 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, с помощью вашего код/сборки так что другие люди могут видеть, какие исключения вы бросить (это именно то, что MS делает в документации MSDN). Вы не можете полагаться на компиляторе, чтобы рассказать вам о необработанных исключениях, однако, как вы можете быть использованы в java.

пройдя через большинство ответов здесь, я хотел бы добавить пару мыслей.

  1. полагаться на комментарии XML-документации и ожидать, что другие будут полагаться на это плохой выбор. Большинство кода C#, с которым я столкнулся, не документирует методы полностью и последовательно с комментариями документации XML. И тогда есть большая проблема, что без проверенных исключений в C#, как вы можете документировать все исключения, которые ваш метод бросает для целей вашего пользователя API знаете, как обращаться со всеми ними по отдельности? Помните, что вы знаете только о тех, которые вы бросаете себе с ключевым словом throw в своей реализации. API, которые вы используете в своей реализации метода, также могут создавать исключения, о которых вы не знаете, потому что они могут быть не задокументированы, и вы не обрабатываете их в своей реализации, поэтому они взорвутся перед лицом вызывающего вашего метода. Другими словами, эти комментарии XML-документации не являются заменой проверенных исключения.

  2. Андреас связал интервью с Андерсом Хейлсбергом в ответах здесь о том, почему команда разработчиков C# решила не проверять исключения. Окончательный ответ на первоначальный вопрос скрыт в этом интервью:

программисты защищают свой код, написав try finally везде, поэтому они будут правильно отступать, если произойдет исключение, но они на самом деле не заинтересованы в обработке исключения.

другими словами, никто не должен быть заинтересован в том, какое исключение можно ожидать для конкретного API, поскольку вы всегда будете ловить их всех везде. И если вы хотите действительно заботиться о конкретных исключениях, как их обрабатывать, зависит от вас, а не от кого-то, определяющего сигнатуру метода с чем-то вроде ключевого слова Java throws, заставляя конкретную обработку исключений для пользователя API.

--

лично я разрываюсь здесь. Я согласен с Андерсом, что проверка исключений не решает проблему без добавления новых, разных проблем. Как и в комментариях к XML-документации, я редко вижу код C# со всем, что завернуто в блоки try finally. Мне кажется, что это действительно ваш единственный вариант и что-то, что кажется хорошей практикой.

на самом деле не проверив исключения в C# можно считать хорошей или плохой вещью.

Я сам считаю, что это хорошее решение, так как проверенные исключения предоставить вам следующие проблемы:

  1. технические исключения, просачивающиеся на уровень бизнеса / домена, потому что вы не можете обрабатывать их должным образом на низком уровне.
  2. они принадлежат сигнатуре метода, которая не всегда хорошо играет с дизайном API.

из-за что в большинстве больших приложений вы увидите следующий шаблон часто, когда проверенные исключения происходят:

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

что по существу означает эмуляцию того, как C#/.NET обрабатывает все исключения.

есть некоторые мимолетные сходства между .Net CodeContract EnsuresOnThrow<> и java throws дескриптор, в том, что оба могут сигнализировать вызывающему как тип исключения, которое может быть вызвано из функции или метода, хотя есть также основные различия между 2:

  • EnsuresOnThrow<> выходит за рамки простого указания, какие исключения могут быть брошены, но также оговаривает условия, при которых они гарантированно будут брошены - это может быть довольно обременительный код в вызываемом методе, если условие исключения не является тривиальным для идентификации. Java throws указывает, какие исключения могут быть брошены (т. е. IMO фокус в .Net находится внутри метода, который заключает контракт, чтобы доказать throw, тогда как в Java фокус смещается на вызывающего, чтобы подтвердить возможность исключения).
  • .Net CC не делает различия между Checked vs Unchecked исключения, которые есть у Java, хотя CC в разделе 2.2.2 руководства упоминается

" используйте исключительные постусловия только для тех исключений, которые вызывающий объект следует ожидать, как часть API"

  • в .Net вызывающий может определить, следует ли делать что-либо с исключением (например, отключив контракты). В Java, вызывающий надо что-то делать, даже если он добавляет throws для того же исключения на своем взаимодействие.

руководство по кодовым контрактам здесь

Вы спрашиваете об этом :

повторное исключение

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
    }