-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Discussion: non-null var pattern #306
Comments
From a readability perspective, I totally missed the |
That's kind of the point. You might prefer |
Ah, I misunderstood, I thought postfix was part of this proposal. |
In the next update to pattern-matching in C#, we will be adding support for a property pattern. For example, if you have a if (o is Point {X is 3, Y is var y}) ... (syntax not necessarily final; we might use If the input is already of the type you're testing, you can omit it and that type is implied. For example, if you have a variable if (p is {X is 3, Y is var y}) ... You can also provide an identifier if you want to refer to the matched entity later: if (GetPoint() is {X is 3, Y is var y} p) ... The semantics of a property pattern is that it first tests if the input is non-null, and then if it is non-null it also matches the named properties against the provided patterns. You can have any number of nested property/pattern pairs. In this example, if As a side-effect, you get a non-null pattern "for free", because "zero" satisfies "any number": if (GetPoint() is {} p) // if the returned point is not null... Given that there is pattern |
@gafter That would make it impossible to use |
The suggestion of overloading var x = someCollection match (
case [ 1, 2, var x ]: $"it's 1, 2, {x}",
case [ 1, .. 20 ]: "it starts with 1 and ends with 20",
case *: "oh, it's neither of them"
); |
We do have object initializers vs. collection initializers with the similar syntax and it wasn't puzzling nor ambiguous in any ways,
Nothing has been told regarding the choice of It's not just that, IMO expr is Type({}, []) The former is a null check and the latter is an empty array. wat. This is highly opinionated but I think |
I think it unfortunate that the dammit operator is going to be used as a "you, Mr Compiler think that's a if (obj is BinaryExpression { Left: var left!, Right: var right! }) ... as well as an earlier suggestion (that I'm not sure still applies) of having the compiler auto-generate null checks on parameters: C1 Foo(C2 bar!) => ...
// being lowered to:
C1 Foo(C2? unsafeBar)
{
if (!(unSafeBar is C2 bar)) throw new ArgumentNullException("bar");
...
} |
the whole
instead of
also could expression declarations be used too? (instead of |
@MkazemAkhgary We definitely do not intend to have expression semantics, such as overload resolution to find an applicable operator |
@gafter thats too much different from what we always had, see my proposal. Im against property pattern,because its too much limited, very unnatural, c# is becoming too complex Thats pile of notations that i hate to use. Please take a step back and see from wider perspective. Sorry for my bad english, but dont throw me away just because i cant talk good. Best regards |
@gafter anyway, with current syntax, how would you want to say if X is between two numbers? for X being equal to 3 its like this. how would that go for ranges?
|
@gafter never mind, I've closed that proposal. I get your point that its about pattern matching not usual expressions, would something like this for ranges work? also
if X is between 0 inclusive and 10 exclusive. also set Y to y |
One possibility for that is active patterns (see #277). So you might define something like: public static bool BetweenPattern(this int value, int min, int max) =>
value >= min && value <= max; then use it like: if (o is Point {X is Between(3, 9), Y is var y}) ... |
very cool, thats something that can be used in normal expressions too. Hmmm @DavidArno |
@gafter Notice how you had to put a comment in your code there to explain what it was doing. Because such a pattern completely obfuscates your intent, which is to check for nullness without actually having the word "null" or a "?" anywhere in the expression. I think expecting such a null check to become idiomatic is awful and certain to lead to bugs because people misunderstand what the code is supposed to be doing. Please let's not turn this language into Perl where secret incantations happen to have non-obvious side effects that your code relies on for correctness. |
@MgSam not to mention that allowing I second abuse of pattern-matching because that's what is called by @gafter himself. here |
This is the syntax I'm imagining we could use here: single_variable_designation
: identifier
| identifier '?'
; Which cleanly fit to the proposed extension to the var_pattern
: 'var' variable_designation
; case var y?:
case var (x, y?):
case (var x, var y?):
// equivalent to
case var y when y != null:
case var (x, y) when y != null:
case (var x, var y) when y != null: Then we could safely disallow the empty property pattern There is an open issue here though, how we should null check a discarded value? Maybe either of, case var _?:
case var ?:
case _?:
case ?: |
@alrz That seems backwards. We use |
Originally proposed in dotnet/roslyn#13432, can be used to null-guard a var pattern,
Alternatively, we could do something like "optional patterns" in Swift,
This allows us to do null check inside deconstruction pattern for each var individually.
In this example we only null-guard
x
buty
still can be null.Note: the simplest case
obj is var x?
wouldn't be ambiguous if we parse?
eagerly as part of the pattern, just likeobj is bool?
which we parse?
as part of the nullable type rather than expecting a ternary.The text was updated successfully, but these errors were encountered: