-
Notifications
You must be signed in to change notification settings - Fork 4.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
C# 7.0 patterns design concerns #13432
Comments
What if you want to typed stuff with the null? null string -> string.Empty etc? More like generics semantics than if (typeof(T) == typeof(sting))
{
}
else if (typeof(T) == typeof(other))
{
} |
|
By the way, I missed this "null-checked name pattern" in F# too... you forced to write ugly |
I understand, and I agree that it would be useful to have a quick way to pattern-match away var person = new Person() { FirstName = "John", LastName = "Smith" };
// later
if (person is Person { LastName is Some(var lastName) }) {
Console.WriteLine($"LastName is not null and is \"{lastName}\".");
} Alternately maybe a if (person is not null) // feels like VB? |
I'll note that in property patterns you will be able to elide the type and obviously, check for nulls. It'd be unfortunate to lose this ability in the simplest form of the patterns. |
The inconsistency comes from blending type declaration and matching into one expression and it's kind of unavoidable. The only way to really fix that would be through the following, which I don't think anybody wants: string s1 = null;
Debug.Assert(s1 is string s2 && object.ReferenceEquals(s1, s2)); Which puts That said, I totally don't think that it should be legal to include string s1 = null;
if (s1 is var s2) { ... } // what's the point of this? |
@HaloFour I think that was initially proposed to make
Looks like a useless declaration expression (#254) because it always return |
cc @gafter |
That's true, it does make sense with I've probably seen the current syntax for so long that I've grown accustomed to it. Having |
I'm always wanting |
@CnSimonChan do we really think, that turning conditional language construct used to do type testing today... into unconditional variable introduction construct tomorrow... is "reasonable"? I'm not sure :) |
I am convinced that var patterns should not do any null check; if it would ever be allowed to use recursive patterns in the context of out parameters in addition to tuple deconstructions (#11293), the simplest form will be a var pattern which must not do any null check. Note that However, I do believe something akin to implicitly unwrapped optionals in Swift would be useful when non-nullable references are introduced in the language. So I think |
Maybe just disallow |
I must admit: this was a bad idea to suggest Anyway, I think two core problems must be addressed in some way:
|
We already discussed this at great length, and found the current state to be the least offensive overall solution. |
What about an "optional pattern" (from Swift), case var x?:
// shorthand for
case var x when x != null: I think this would be very useful, specifically in scenarios mentioned by OP. |
@alrz The OP's use cases are recursive patterns, which are not part of C# 7. |
We'll be tracking language design issues in the csharplang repo, so I'm closing this in the Roslyn repo. If there are still issues here that interest you, you are most welcome to open issues there. |
Hi Roslyn team!
After observing the C# 7.0 design proposals and trying to imagine future ReSharper features/suggestions/transformations that would help C# developers to adopt all the great language improvements, I have a few design concerns around patterns I wish to express here. I really hope this would be any helpful to anybody.
1. The conditional nature of
is
expressionOrdinary
is
expression is actually not only type-checking, but also the null-checking expression in user's intuition......and 'var' is the "no-op" construct that just enables the type inference...
Both of those assumptions/intuitions are broken by the
x is var y
construct:Just like
x is *
, thex is var t
construct has no real use. I can't even use it to "declare" the variable for expression somewhere deep inside other expressions without special method taking dummy booleantrue
fromis
expression likeFoo(Bar( Let(Baz() is var baz, h * h) ))
.I really like the idea to extend existing
is
andswitch
constructs, but maybe C# 7.0 can save user's intuition by splitting the sets of patterns into conditional/unconditional ones and restricting the use of unconditional patterns insideis
expressions (andswitch
as well?). This would help preserving the "conditional nature" ofis
expression and avoid it's use to simply introduce some names (we would have better ways to do this, right?).2. The kind of "deconstruction" we can use the most in C# code
In short: what we really need is the "!= null" + variable pattern.
After looking at my daily code in ReSharper (which is quite similar to code you have in Roslyn: lot of null and type checking over trees of closed type hierarchies), I realized I can only rewrite a very limited set of code in terms of the pattern-matching, even with all the reach proposals like positional/property patterns now postponed to C# 7+.
For example, this is the typical "deconstruction" routine:
I can really turn it into the declarative pattern with property patterns, except the sad part - there is no way to express that
leftOperand
andrightOperand
pattern variables are expected to be non-null, so I have to do manual null-checks after pattern matching:Technically, I can workaround null-checks with the use of type patterns (damn, this looks nearly awesome!):
But I'm not sure this is the desired use of type patterns, since if we change the type of
LeftOperand
/RightOperand
, the pattern code would compile fine but with dramatic semantic change.I believe it's really important to have "null-checking" pattern from the beginning of "patterns invasion" into C#, since null-checks are really common thing to do during "deconstruction" of the data in C#. Type pattern has implicit null check, I believe property pattern is doing it is well, but there is no simple way to get a fresh variable bound to non-null value.
I can imagine splitting variable pattern into conditional "null-checking variable" and unconditional "nullable variable" patterns, maybe expressed in a
x is var notNull
andx is var? canBeNull
forms respectively. This would preserve our intuition of conditionalis
expression + preserve type-inference-enabling nature ofvar
:So, "null-checking variable pattern" is really a form of type pattern with type-inferred type. And the explicit question mark for nullable variables patterns would notify user for possible null checks needed:
I know that would slightly break intuition around
var
-as-a-thing-that-can-be-null
, but we want lessnull
s in future C# and nullable reference types explicitly expressed in a language syntax, do we?3. Constness of
is
expressions with unconditional patterns.Even if
is
expression is allowed to have unconditional patterns, I expectis
expression to became constant boolean expression withtrue
as a value, so we get the compiler warning on unreachable code:The text was updated successfully, but these errors were encountered: