Proposal: Guard statement #138
Replies: 32 comments 6 replies
-
Method contracts #105 is trying to solve the same problem. |
Beta Was this translation helpful? Give feedback.
-
@gulshan The purpose of guard statement is covered more than just parameter. It can be used on variable later on |
Beta Was this translation helpful? Give feedback.
-
I would still go against adding void Guard(string s)
{
return if(!int.TryParse(s, out var value))
{
// handle or report the problem
// auto return after this block
}
// use value
} |
Beta Was this translation helpful? Give feedback.
-
@Thaina Isn't |
Beta Was this translation helpful? Give feedback.
-
You've already linked dotnet/roslyn#11562 which was on the table for the LDM team before they decided to make |
Beta Was this translation helpful? Give feedback.
-
@gulshan Not quite What I would compare it to To put it simply. We may have code like this void DoSomething()
{
if(condition)
{
// 20 lines of code
}
else
{
// 40 lines of code
}
} We might try to make less indent void DoSomething()
{
if(condition)
{
// 20 lines of code
return;
}
// 40 lines of code
} But it will not so obvious. It will be a bug if we forget to add return in the last void DoSomething()
{
return if(condition) // Much more obvious
{
// 20 lines of code
}
// 40 lines of code
} |
Beta Was this translation helpful? Give feedback.
-
@Thaina |
Beta Was this translation helpful? Give feedback.
-
@gulshan Indeed it opposite check But this is just minor Not difference. I just don't like adding new keyword while we can reuse keyword we have. |
Beta Was this translation helpful? Give feedback.
-
@gulshan And it not only about "the parameters are not valid" there could be any kind of logic with condition that if it meet some condition it will do one branch of logic and return void DoSomething()
{
return if(condition0)
{
// 8 lines of code
}
return if(condition1)
{
// 8 lines of code
}
return if(condition2)
{
// 8 lines of code
}
// 12 lines of code for not met any condition above
} |
Beta Was this translation helpful? Give feedback.
-
I don't see how guard (b > 0) else throw new IllegalArgumentException(nameof(b)); is any better than if (b <= 0) throw new IllegalArgumentException(nameof(b)); I suppose it could be easier to read and an automatic negation but I don't think that's a big enough reason to add a feature to C#. |
Beta Was this translation helpful? Give feedback.
-
@michaelcfanning Having keyword like As I was state above. This feature could compare to But Same reason when you have a code block that branching off. To ensure that when condition don't match it will not touch a block of code below if block. guard statement could protect you |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
It looks to me as if guard (b > 0) else throw new IllegalArgumentException(nameof(b)); instead of if (!( b > 0 )) throw new IllegalArgumentException(nameof(b)); And I don't like And just by looking at it I don't really get what return if(condition0)
{
// 8 lines of code
} will mean. As long as it is not kind of intuitive, these constructs should not be allowed! |
Beta Was this translation helpful? Give feedback.
-
I'm not sure why it needs to be |
Beta Was this translation helpful? Give feedback.
-
@eyalsk |
Beta Was this translation helpful? Give feedback.
-
IIRC, the idea behind the original guard statement was to leak variables into the outer scope and ensure that something bottom-typed like |
Beta Was this translation helpful? Give feedback.
-
Without the explicit scope leakage benefits there is little reason to implement I will say that the |
Beta Was this translation helpful? Give feedback.
-
Code Contracts (#105) seems to be the better idea. No need to reinvent the squared wheel. |
Beta Was this translation helpful? Give feedback.
-
@MovGP0 I really hope this will get implemented at some point. :) |
Beta Was this translation helpful? Give feedback.
-
@MovGP0 I think it's not the point of this feature. Code Contract is not compile time |
Beta Was this translation helpful? Give feedback.
-
@Thaina If #105 will get implemented then it will be part of the language and may or may not be done at compile-time depends on the design. |
Beta Was this translation helpful? Give feedback.
-
@Thaina To my knowledge, Code Contracts are enforced by the CLR since v4.0 (ca. 2008) at runtime. Violations cause an exception in the calling code. |
Beta Was this translation helpful? Give feedback.
-
@MovGP0 I think so that's why it not related to guard syntax. guard syntax main purpose is to block usage of variable at compile time |
Beta Was this translation helpful? Give feedback.
-
@Thaina But it might get implemented as part of the language... and then the guard construct would be useless. |
Beta Was this translation helpful? Give feedback.
-
Note: Method contracts will probably not cover pattern matching. |
Beta Was this translation helpful? Give feedback.
-
Code contracts should cover this. |
Beta Was this translation helpful? Give feedback.
-
Guard has another idea. You will lock the local variable not an inveted if !!!! public MyViewModel ViewModel { get; set; }
public async Task DoSomethingAsync()
{
if (ViewModel == null) return;
// Start Long Task
await Task.Delay(5000);
// ViewModel possible get null here
await ViewModel.DoSomethingElseAsync();
}
...
public void Dispose()
{
ViewModel = null;
} How guard will protect your variable here: public MyViewModel ViewModel { get; set; }
public async Task DoSomethingAsync()
{
guard (var vm = ViewModel) else {
return;
}
// Start Long Task
await Task.Delay(5000);
// vm is not null for sure
await vm.DoSomethingElseAsync();
} |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
The way elixir handles this is oh so slick, and C# could do something quite similar without new keywords or anything too confusing, you just pattern match off of the function header.
Sooo much cleaner than statements within the method - it makes it blatantly obvious when each method is called and you can guarantee that within that method x will be validated on whatever rules are necessary. C# 9 gets us kinda sorta close, but it's still nothing near as slick as the above example.
|
Beta Was this translation helpful? Give feedback.
-
'Guard Let' ConsiderationThis proposal and discussion missed out on what is one of the most fundamental and valuable uses of Swift's In addition to inverting the 'if' check, the Given:
Currently (without pattern-matching):
Currently (with pattern-matching):
With 'guard let':
**With current pattern While we could hack around this with the current Null Checks pattern matching, the main point is that the inverse declaration pattern is not currently supported and does not allow for the same semantics to be achieved. |
Beta Was this translation helpful? Give feedback.
-
Background
Swift 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.
Problem
If we have a function
Foo
that takes an integer that must be positive (> 0
), we can write that as:Proposed Solution: guard statements
Benefits
The guard statement introduces two benefits over
if
-based guards:Grammar
See Also
Beta Was this translation helpful? Give feedback.
All reactions