How to correctly execute the method of returning exceptions inside the method of returning in C #

See the edits below to reproduce the behavior that I am describing in this issue.

The following program will never end because the yield return construct in C # calls the GetStrings() method indefinitely when an exception is thrown.

 class Program { static void Main(string[] args) { // I expect the Exception to be thrown here, but it not foreach (var str in GetStrings()) { Console.WriteLine(str); } } private static IEnumerable<string> GetStrings() { // REPEATEDLY throws this exception throw new Exception(); yield break; } } 

For this trivial example, I could obviously use return Enumerable.Empty<string>(); and the problem will disappear. However, in a more interesting example, I would expect the exception to be thrown once, and then the method will cease to be called and throw an exception in the method that "consumes" IEnumerable .

Is there any way to produce this behavior?

EDIT: ok, the problem is different than i thought. The program above does not end, and the foreach behaves like an infinite loop. The program below terminates and the exception is displayed on the console.

 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; } } 

Why does the try ... catch make a difference in this case? This is very strange to me. Thanks to @AndrewKilburn for his reply already for pointing me to this.

EDIT # 2: On the command line, the program does the same thing in both cases. In Visual Studio Enterprise 2015, Update 2, whether compiling in Debug or Release, the behavior above is what I see. With try ... catch program ends with an exception, and without it, Visual Studio never closes the program.

EDIT 3: Fixed For me, the problem was resolved using @MartinBrown's answer. When I turn off the Visual Studio option under Debug> Preferences> Debug> General> Untie Call Stack on Unhandled Exceptions, this problem will disappear. When I check the box again, the problem will return.

+6
source share
4 answers

The behavior discussed here is not an error in the code; rather, this is a side effect of the Visual Studio debugger. This can be fixed by disabling stack erasure in Visual Studio. Try entering Visual Studio options. Debugging / General and unchecking "Defrost call stack on unhandled exceptions." Then run the code again.

What happens when your code falls into a completely unhandled exception. Visual Studio discards the call stack immediately before the line of code that caused the exception. It does this so that you can edit the code and continue execution with the edited code.

The above problem looks like an infinite loop, because when you restart the execution in the debugger, the next line to start is the one that just threw the exception. Outside of the debugger, the call stack will be completely unwound on the unhandled exception and therefore will not lead to the same loop that you will receive in the debugger.

This function of unlocking the stack can be disabled in the settings, it is enabled by default. If you disable it, you will stop editing the code and continue without first unwinding the stack itself. However, this is fairly easy to do either from the call stack window, or simply by selecting "Enable Editing" from the exception helper.

+5
source
  class Program { static void Main(string[] args) { try { foreach (var item in GetStrings()) { Console.WriteLine(); } } catch (Exception ex) { } } private static IEnumerable<string> GetStrings() { // REPEATEDLY throws this exception throw new Exception(); yield break; } } 

Introducing him into a catch attempt, he breaks free and does everything you need.

0
source

The next program will never end

It's a lie. The program will end soon.

because the return return construct in C # calls the GetStrings() method indefinitely when an exception is thrown.

This is not true. It does not do this at all.

I would expect the exception to be thrown once, after which the method ceases to be called and throws an exception in the method that "consumes" IEnumerable .

What exactly is going on.

Is there any way to produce this behavior?

Use the code that you have already specified.

0
source
 class Program { public static int EnumerableCount; static void Main(string[] args) { EnumerableCount = 0; try { foreach (var str in GetStrings()) { Console.WriteLine(str); Console.Read(); } } catch (Exception e) { Console.WriteLine(e); Console.Read(); } } private static IEnumerable<string> GetStrings() { EnumerableCount++; var errorMessage = string.Format("EnumerableCount: {0}", EnumerableCount); throw new Exception(errorMessage); yield break; } } 

has the following output:

 System.Exception: EnumerableCount: 1 at {insert stack trace here} 

The thread goes to the GetStrings () method for the first iteration, the exception is thrown and broken in the Main () method. After logging in, the program will exit.

Removing try catch in the Main () method causes the exception to not be thrown. The output will be as follows:

 Unhandled Exception: System.Exception: EnumerableCount: 1 at {insert stack trace here} 

and the program will work.

0
source

All Articles