-
Notifications
You must be signed in to change notification settings - Fork 6k
Add explanation of why the when
contextual keyword is better than if/else in catch blocks
#47887
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
7
commits into
main
Choose a base branch
from
copilot/fix-40661
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+191
−0
Open
Changes from 2 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
e057611
Initial plan
Copilot 465c5e2
Add detailed explanation of when keyword and exception filters
Copilot b2f3e32
Update docs/csharp/language-reference/statements/exception-handling-s…
BillWagner bfbf5d9
Update docs/csharp/language-reference/statements/exception-handling-s…
BillWagner 4b6db00
Address review feedback: Add stack trace preservation explanation
Copilot a2ca51e
Address review feedback: Fix punctuation, emphasis, headings and list…
Copilot 18fd2be
Apply suggestions from code review
BillWagner File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
152 changes: 152 additions & 0 deletions
152
...anguage-reference/statements/snippets/exception-handling-statements/WhenFilterExamples.cs
BillWagner marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
|
||
namespace ExceptionFilterExamples | ||
{ | ||
public static class WhenFilterExamples | ||
{ | ||
// <ExceptionFilterVsIfElse> | ||
public static void DemonstrateStackUnwindingDifference() | ||
{ | ||
var localVariable = "Important debugging info"; | ||
|
||
try | ||
{ | ||
ProcessWithExceptionFilter(localVariable); | ||
} | ||
catch (InvalidOperationException ex) when (ex.Message.Contains("filter")) | ||
{ | ||
// Exception filter: Stack not unwound yet | ||
// localVariable is still accessible in debugger | ||
// Call stack shows original throwing location | ||
Console.WriteLine($"Caught with filter: {ex.Message}"); | ||
Console.WriteLine($"Local variable accessible: {localVariable}"); | ||
} | ||
|
||
try | ||
{ | ||
ProcessWithTraditionalCatch(localVariable); | ||
} | ||
catch (InvalidOperationException ex) | ||
{ | ||
// Traditional catch: Stack already unwound | ||
// Some debugging information may be lost | ||
if (ex.Message.Contains("traditional")) | ||
{ | ||
Console.WriteLine($"Caught with if: {ex.Message}"); | ||
Console.WriteLine($"Local variable accessible: {localVariable}"); | ||
BillWagner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
else | ||
{ | ||
throw; // Re-throws and further modifies stack trace | ||
} | ||
} | ||
} | ||
|
||
private static void ProcessWithExceptionFilter(string context) | ||
{ | ||
throw new InvalidOperationException($"Exception for filter demo: {context}"); | ||
} | ||
|
||
private static void ProcessWithTraditionalCatch(string context) | ||
{ | ||
throw new InvalidOperationException($"Exception for traditional demo: {context}"); | ||
} | ||
// </ExceptionFilterVsIfElse> | ||
|
||
// <MultipleConditionsExample> | ||
public static void HandleFileOperations(string filePath) | ||
{ | ||
try | ||
{ | ||
// Simulate file operation that might fail | ||
ProcessFile(filePath); | ||
} | ||
catch (IOException ex) when (ex.Message.Contains("access denied")) | ||
{ | ||
Console.WriteLine("File access denied. Check permissions."); | ||
} | ||
catch (IOException ex) when (ex.Message.Contains("not found")) | ||
{ | ||
Console.WriteLine("File not found. Verify the path."); | ||
} | ||
catch (IOException ex) when (IsNetworkPath(filePath)) | ||
{ | ||
Console.WriteLine($"Network file operation failed: {ex.Message}"); | ||
} | ||
catch (IOException) | ||
{ | ||
Console.WriteLine("Other I/O error occurred."); | ||
} | ||
} | ||
|
||
private static void ProcessFile(string filePath) | ||
{ | ||
// Simulate different types of file exceptions | ||
if (filePath.Contains("denied")) | ||
throw new IOException("File access denied"); | ||
if (filePath.Contains("missing")) | ||
throw new IOException("File not found"); | ||
if (IsNetworkPath(filePath)) | ||
throw new IOException("Network timeout occurred"); | ||
} | ||
|
||
private static bool IsNetworkPath(string path) | ||
{ | ||
return path.StartsWith(@"\\") || path.StartsWith("http"); | ||
} | ||
// </MultipleConditionsExample> | ||
|
||
// <DebuggingAdvantageExample> | ||
public static void DemonstrateDebuggingAdvantage() | ||
{ | ||
var contextData = new Dictionary<string, object> | ||
{ | ||
["RequestId"] = Guid.NewGuid(), | ||
["UserId"] = "user123", | ||
["Timestamp"] = DateTime.Now | ||
}; | ||
|
||
try | ||
{ | ||
// Simulate a deep call stack | ||
Level1Method(contextData); | ||
} | ||
catch (Exception ex) when (LogAndFilter(ex, contextData)) | ||
{ | ||
// This catch block may never execute if LogAndFilter returns false | ||
// But LogAndFilter can examine the exception while the stack is intact | ||
Console.WriteLine("Exception handled after logging"); | ||
} | ||
} | ||
|
||
private static void Level1Method(Dictionary<string, object> context) | ||
{ | ||
Level2Method(context); | ||
} | ||
|
||
private static void Level2Method(Dictionary<string, object> context) | ||
{ | ||
Level3Method(context); | ||
} | ||
|
||
private static void Level3Method(Dictionary<string, object> context) | ||
{ | ||
throw new InvalidOperationException("Error in deep call stack"); | ||
} | ||
|
||
private static bool LogAndFilter(Exception ex, Dictionary<string, object> context) | ||
{ | ||
// This method runs before stack unwinding | ||
// Full call stack and local variables are still available | ||
Console.WriteLine($"Exception occurred: {ex.Message}"); | ||
Console.WriteLine($"Request ID: {context["RequestId"]}"); | ||
Console.WriteLine($"Full stack trace preserved: {ex.StackTrace}"); | ||
|
||
// Return true to handle the exception, false to continue search | ||
return ex.Message.Contains("deep call stack"); | ||
} | ||
// </DebuggingAdvantageExample> | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.