См. Правки ниже для воспроизведения поведения, которое я описываю в этой проблеме.Как правильно выполнить метод возврата исключений внутри метода возврата в C#
Следующая программа никогда не закончится, поскольку конструкция yield return
в C# вызывает метод GetStrings()
неопределенно, когда генерируется исключение.
class Program
{
static void Main(string[] args)
{
// I expect the Exception to be thrown here, but it's not
foreach (var str in GetStrings())
{
Console.WriteLine(str);
}
}
private static IEnumerable<string> GetStrings()
{
// REPEATEDLY throws this exception
throw new Exception();
yield break;
}
}
Для этого простейшего примера, я мог бы, очевидно, использовать return Enumerable.Empty<string>();
вместо этого, и проблема уходит. Однако в более интересном примере я ожидал бы, что исключение будет выброшено один раз, а затем метод перестанет быть вызванным и выкинет исключение в методе, который «потребляет» IEnumerable
.
Есть ли способ произвести такое поведение?
EDIT: хорошо, проблема отличается от того, что я сначала подумал. Программа выше не заканчивается, и цикл foreach
ведет себя как бесконечный цикл. Программа ниже завершается, и исключение отображается на консоли.
class Program
{
static void Main(string[] args)
{
try
{
foreach (var str in GetStrings())
{
Console.WriteLine(str);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static IEnumerable<string> GetStrings()
{
throw new Exception();
yield break;
}
}
Почему try
... catch
блок сделать разницу в этом случае? Мне это очень странно. Спасибо @ AndrewKilburn за его ответ уже за то, что он указал мне на это.
EDIT # 2: В командной строке программа выполняет одно и то же в обоих случаях. В Visual Studio Enterprise 2015, обновление 2, будь то компиляция в Debug или Release, поведение выше - это то, что я вижу. С try
... catch
программа заканчивается исключением, и без нее Visual Studio никогда не закрывает программу.
EDIT # 3: Исправлено Для меня проблема была решена путем ответа @MartinBrown. Когда я отключу опцию Visual Studio в разделе «Отладка»> «Параметры»> «Отладка»> «Общие»> «Отвяжите стек вызовов при необработанных исключениях», эта проблема исчезнет. Когда я снова поставлю флажок, проблема вернется.
Я попробовал, и он бросает только один раз. В случае обертывания 'foreach' с исключением' try catch' был пойман только один раз, и программа завершает работу. Правильно ли я это понял? – Szer
Хммм, я не вижу этого поведения. Позвольте мне снова проверить, чтобы быть уверенным. Поведение, которое я вижу, это то, что исключение выбрано, и оно каким-то образом зацепилось за кулисами, а цикл 'foreach' ведет себя как бесконечный цикл. –
@Szer См. Мое редактирование, блоки 'try' ...' catch', похоже, имеют значение в том, работает ли цикл foreach как бесконечный цикл. Это имеет какое-то значение для вас? –