{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/8181","repository_url":"https://api.github.com/repos/dotnet/roslyn","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/8181/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/8181/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/8181/events","html_url":"https://github.com/dotnet/roslyn/issues/8181","id":128860688,"number":8181,"title":"Proposal: Guard statement in C#","user":{"login":"Eyas","id":554424,"avatar_url":"https://avatars.githubusercontent.com/u/554424?v=3","gravatar_id":"","url":"https://api.github.com/users/Eyas","html_url":"https://github.com/Eyas","followers_url":"https://api.github.com/users/Eyas/followers","following_url":"https://api.github.com/users/Eyas/following{/other_user}","gists_url":"https://api.github.com/users/Eyas/gists{/gist_id}","starred_url":"https://api.github.com/users/Eyas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Eyas/subscriptions","organizations_url":"https://api.github.com/users/Eyas/orgs","repos_url":"https://api.github.com/users/Eyas/repos","events_url":"https://api.github.com/users/Eyas/events{/privacy}","received_events_url":"https://api.github.com/users/Eyas/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/0%20-%20Backlog","name":"0 - Backlog","color":"CCCCCC"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":14,"created_at":"2016-01-26T15:50:28Z","updated_at":"2016-05-25T20:07:11Z","closed_at":null,"body":"## Background\r\n\r\nSwift has a guard statement that can be very valuable in writing code that is easy to reason about. See [Swift Guard Statement - why you should use it](http://ericcerney.com/swift-guard-statement/).\r\n\r\n## Problem\r\nIf we have a function `Foo` that takes an integer that must be positive (`> 0`), we can write that as:\r\n```cs\r\nBar Foo_alt1(int b) {\r\n    if (b > 0) {\r\n        // all of our code is surrounded by checks for the condition.\r\n        // special handling of condition is far away from the statement of what the condition is\r\n        // extra indent, extra nesting, etc.\r\n    } else {\r\n        throw new IllegalArgumentException(nameof(b));\r\n    }\r\n}\r\n\r\nBar Foo_alt2(int b) {\r\n    // 'syntactic sugar' disadvantage is that now we check for the \"negative\"\r\n    // condition instead of the positive. this might be natural in cases of null checking or\r\n    // other simple checks, but can become burdensome in complex cases of many comparisons\r\n    // and logical operators.\r\n    if (b <= 0) {\r\n        throw new IllegalArgumentException(nameof(b));\r\n    } else {\r\n        // rest of code to handle the normal case is here.\r\n        // 'excessive' nesting and indentation\r\n        return foo;\r\n    }\r\n}\r\n\r\nBar Foo_alt3(int b) {\r\n    // 'syntactic sugar' disadvantage is that now we check for the \"negative\"\r\n    // condition instead of the positive. this might be natural in cases of null checking or\r\n    // other simple checks, but can become burdensome in complex cases of many comparisons\r\n    // and logical operators.\r\n    if (b <= 0) {\r\n        throw new IllegalArgumentException(nameof(b));\r\n    }\r\n\r\n    // rest of code to handle the normal case is here.\r\n    // we choose not to resort to nesting, but in doing so, we lose an important compile-time check:\r\n    // a programmer error might result in the if-block above not returning or throwing, thus\r\n    // causing the control flow to drop off into the \"normal\" code\r\n    return foo;\r\n}\r\n```\r\n## Proposed Solution: `guard` statements\r\n```cs\r\nBar Foo(int b) {\r\n    // state that b must be a positive integer\r\n    guard (b > 0) else {\r\n        throw new IllegalArgumentException(nameof(b));\r\n    }\r\n    // compiler verifies that the guard-block throws or returns, thus\r\n    // guaranteeing that code here will satisfy the guard condition.\r\n    // ... do something with b without worrying about edge cases\r\n}\r\n```\r\n## Benefits\r\nThe guard statement introduces two benefits over `if`-based guards:\r\n\r\n1. Syntactic sugar of declaring the positive condition we would like to meet after the guard, rather than the negatives\r\n2. Compile-time checking of the fact that the guard clause ends control flow by returning or throwing\r\n3. One less indent :)\r\n\r\n## Grammar\r\n```\r\nguard-statement\r\n    : 'guard' ( boolean-expression ) 'else' embedded-statement\r\n    ;\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/221691282","html_url":"https://github.com/dotnet/roslyn/issues/8181#issuecomment-221691282","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/8181","id":221691282,"user":{"login":"gafter","id":3804346,"avatar_url":"https://avatars.githubusercontent.com/u/3804346?v=3","gravatar_id":"","url":"https://api.github.com/users/gafter","html_url":"https://github.com/gafter","followers_url":"https://api.github.com/users/gafter/followers","following_url":"https://api.github.com/users/gafter/following{/other_user}","gists_url":"https://api.github.com/users/gafter/gists{/gist_id}","starred_url":"https://api.github.com/users/gafter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gafter/subscriptions","organizations_url":"https://api.github.com/users/gafter/orgs","repos_url":"https://api.github.com/users/gafter/repos","events_url":"https://api.github.com/users/gafter/events{/privacy}","received_events_url":"https://api.github.com/users/gafter/received_events","type":"User","site_admin":false},"created_at":"2016-05-25T20:07:11Z","updated_at":"2016-05-25T20:07:11Z","body":"What `guard` has to do with pattern-matching is that pattern variables introduced in the expression of a `guard` statement would be in scope in the enclosing block."}}
{"actor":{"display_login":"gafter"}}