Как использовать ключевое слово throws в стиле Java в C #? - PullRequest
78 голосов
/ 12 августа 2010

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

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

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

Ответы [ 8 ]

88 голосов
/ 12 августа 2010

Оператор запрашивает эквивалент 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...
}
66 голосов
/ 12 августа 2010

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

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

Если вы хотите справиться с этим, а затем повторно бросить, вы можете сделать следующее:

try
{
  // code that throws an exception
}
catch(ArgumentNullException ex)
{
  // code that handles the exception
  throw;
}
22 голосов
/ 23 июля 2013

Да, это старая тема, однако я часто нахожу старые темы, когда ищу ответы, поэтому решил добавить что-нибудь полезное, что нашел.

Если вы используете 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);
    }
17 голосов
/ 12 августа 2010

Вот ответ на аналогичный вопрос, который я только что финансировал на bytes.com :

Короткий ответ - нет, в C # нет проверенных исключений.Разработчик языка обсуждает это решение в этом интервью:

http://www.artima.com/intv/handcuffs.html

Самое близкое, что вы можете получить, - это использовать теги в вашей XML-документации и распространять сгенерированные NDoc документы с вашим кодом/ сборки, чтобы другие люди могли видеть, какие исключения вы выбрасываете (что именно то, что MS делает в документации MSDN).Однако вы не можете полагаться на то, что компилятор расскажет вам о необработанных исключениях, как вы привыкли в java.

5 голосов
/ 25 мая 2017

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

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

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

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

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

-

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

3 голосов
/ 12 августа 2010

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

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

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

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

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

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

3 голосов
/ 12 августа 2010

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

Повторное создание исключения

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
    }
2 голосов
/ 18 сентября 2013

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

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

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

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

Код контрактов здесь вы найдете здесь

...