Replies: 32 comments
-
Duplicate of #1468. Soon these (or similar syntax) will give you the same result: void DoSomething(Shape s)
{
if (s is Circle { Radius > 10 })
{
...
}
else if (s is Rectangle { Width > 10 })
{
...
}
} void DoSomething(Shape s) => s match
{
Circle c when c.Radius > 10 => ...,
Rectangle r when r.Width > 10 => ...
}; Where your proposal can benefit is playing well with partial classes and inheritance. Those alone are probably not compelling enough to warrant the work required to deliver the feature. |
Beta Was this translation helpful? Give feedback.
-
(Actually my second example might not work given the |
Beta Was this translation helpful? Give feedback.
-
I think my proposal is better. void DoSomething(Shape s)
{
if (s is Circle { Radius < 5 })
{
...
}
else if (s is Rectangle { Width > 10 })
{
...
}
else if (s is Triangle{ Width > 10 })
{
...
}
else if (s is Circle{ Radius> 10 })
{
...
}
else if (s is Square{ X > 100 })
{
...
}
else if (s is Triangle{ Width > 10 })
{
...
}
else if (s is Square{ Y> 10 })
{
...
}
...
} Your second example is not good for big body of method. We have to write extra methods void DoSomething(Shape s) => s switch
{
Circle c when c.Radius > 10 => MethodCircleWithRadiusMore10(c),
Rectangle r when r.Width > 10 => MethodRectangleWithRadiusMore10(r)
};
void MethodCircleWithRadiusMore10( Circle c)
{
//thousands of lines of code here
}
void MethodRectangleWithRadiusMore10( Rectangle r)
{
//thousands of lines of code here
} |
Beta Was this translation helpful? Give feedback.
-
A |
Beta Was this translation helpful? Give feedback.
-
Your proposal doesn't address precedence. You have two tests for |
Beta Was this translation helpful? Give feedback.
-
I think it has to be compilation error, something about ambiguity. |
Beta Was this translation helpful? Give feedback.
-
This proposal doesn't make sense to decide at compile time. The compiler can't know runtime property values. And the compiler either doesn't know the subclass of |
Beta Was this translation helpful? Give feedback.
-
I think compiler can find ambiguity if we use constants like in my examples |
Beta Was this translation helpful? Give feedback.
-
@bondsbw @Malanin this proposal looks like it's inspired by ML-like languages, but in ML-like languages the order of function declaration matters (that's why you need However, switch expressions and recursive patterns will let you write quite concise code structurally similar to ML: public void DoSomething(Shape s) => s switch {
Circle c when c.Radius > 10 => ... ,
Rectangle r when r.Width > 10 => ... ,
...
}; This makes me wonder if we need shorthand syntax for switch expressions as method bodies. This final semicolon looks so out of place. |
Beta Was this translation helpful? Give feedback.
-
I have two problems with this proposal; one minor and one major. Firstly, the minor one: your choice of syntax. If I see DoSomething(Shape s) when s is Circle => s.Radius>10 I see an expression bodied method that will execute if public void DoSomething(Shape s) when s is Circle && s.Radius>10
{
} But this point is fairly moot compared with my main concern: encouraging weak cohesion, especillay when we take into account your comment "Your second example is not good for big body of method. We have to write extra methods". If I have a method containing a switch statement that is thousands of lines long, the absolute last thing I'd want is that switch statement replaced with a bunch of methods, each a thousand lines long, where each method contains part of the story as to which one would get executed in a particular circumstance. Having a small public method that does the switch, and a bunch of private methods that handle each case is exactly what I'd want. So you example code is the correct way to do things in my view (save for the "thousands of lines of code here" part; that's inexcusable always): void DoSomething(Shape s) => s switch
{
Circle c when c.Radius > 10 => DoSomethingWithCircleWithRadiusGreaterThan10(c),
Rectangle r when r.Width > 10 => DoSomethingWithRectWithWidthGreaterThan10(r)
};
void DoSomethingWithCircleWithRadiusGreaterThan10(Circle c)
{
//a few lines of code here
}
void DoSomethingWithRectWithWidthGreaterThan10(Rectangle r)
{
//a few lines of code here
} Though of course we should also remember that the switch expression will not work with |
Beta Was this translation helpful? Give feedback.
-
@DavidArno, I agree with your first statement void DoSomething(Shape s) => s switch
{
Circle c when c.Radius > 10 => DoSomethingWithCircleWithRadiusGreaterThan10(c),
Rectangle r when r.Width > 10 => DoSomethingWithRectWithWidthGreaterThan10(r)
};
void DoSomethingWithCircleWithRadiusGreaterThan10(Circle c)
{
//a few lines of code here
}
void DoSomethingWithRectWithWidthGreaterThan10(Rectangle r)
{
//a few lines of code here
} Second Example: public void DoSomething(Shape s) when s is Circle && s.Radius>10
{
//a few lines of code here
}
public void DoSomething(Shape s) when s is Rectangle && s.Width > 10
{
//a few lines of code here
} Just compare this two examples. My proposal make code cleaner, shorter and more readable. |
Beta Was this translation helpful? Give feedback.
-
@Malanin I think your proposal will make code harder to understand and navigate. It will be harder to understand, because it won't be clear which version of the method will be executed. To some degree, that's already the case with overloads, but you're making that much worse. It will be harder to navigate, because today I can easily use a gesture in my IDE to find which method or overload will be called by a line of code. But you proposal will make that navigation much harder: which version of the method should the IDE show, if any one of them can be executed at runtime? |
Beta Was this translation helpful? Give feedback.
-
@svick, I don't see a problem with IDE. If we use interface instead of class ( when we use Dependency Injection), we also can't navigate on needed method, but visual studio show list of variants and we chose one we want. |
Beta Was this translation helpful? Give feedback.
-
@Malanin You can at least navigate to the interface method declaration, which can give you some useful information. Also: how will your proposal deal with XML documentation comments and attributes (including those on method parameters)? |
Beta Was this translation helpful? Give feedback.
-
All methods have a single purpose and there is no need to write difference description for each method, methods has the same parameters. I think IDE can choose any xml comment. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour, It is not big problem. We can use only constants, and compiler can define error. public void DoSomething(Shape s) when s is Circle && s.Radius>10{}
public void DoSomething(Shape s) when s is Circle && s.Radius>12{} I think, compiler can find it ambiguity. |
Beta Was this translation helpful? Give feedback.
-
Indeed, other proposals to try to bring pattern matching into the method signature have been declined specifically for that reason. This proposal seems to gloss over a lot of the specific details and only really mentions either case guards or recursive patterns. But if it approaches trying to match on types themselves via overloads that would effectively result in changing behavior. Pattern matching already only works on constants and lexical ordering is already a critical concern. A pattern guard (or recursive pattern) could be any combination of conditions. It'd be impossible (and certainly undesirable) to have the compiler assume in what order they should be matched. |
Beta Was this translation helpful? Give feedback.
-
Your first example clearly separates out one method with responsible for selecting the required functionality. from a set of methods, each of which performs a specific function. This is highly cohesive; each method has its own responsibility and that responsibility sits solely with that method. Sure, it's a bit longer; sometimes more code is better. I also feel that it's far cleaner, readable and most important, reasonable, ie it's easier to reason ("execute in your head") highly cohesive code. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour, do you think formal verification can't solve these problems? |
Beta Was this translation helpful? Give feedback.
-
No, I don't. The two following comparisons are perfectly legal and can match in either order. There is no "correct" way to order them. public void foo(Shape s) when s is Rectangle && s.Width > 100 { }
public void foo(Shape s) when s is Rectangle && s.Area > 150 { } Reordering those methods in the class should not change the business logic. And, as mentioned, with |
Beta Was this translation helpful? Give feedback.
-
Yes, and so that's why it wil be Compilation error. Compiler can use formal verification and find this error. |
Beta Was this translation helpful? Give feedback.
-
If that kind of match would result in a compiler error then I think that this feature would not only be useless but also exceptionally frustration as in my opinion the vast majority of pattern matching expressions will result in this case. Would the compiler also fail in the case of non-exhaustive matches? |
Beta Was this translation helpful? Give feedback.
-
This is a dup of #1468 In my opinion, this is something we would likely never do in C#. The separation of declaration (signature) from implementation is something we value highly. |
Beta Was this translation helpful? Give feedback.
-
Would be great if we only could use void-returning methods in switch expressions.. void M(object o) => o switch
{
T1 t => M(t),
T2 t => M(t),
}; Nobody has expected the same in ternaries but with switch expressions the limitation is more visible. |
Beta Was this translation helpful? Give feedback.
-
While I dislike the idea of some sort of property condition, being able to separate out method declarations for instances of a closed algebraic datatype is somewhat appealing: Given ADT pseudo-syntax:
It could be useful to encode the switch directly into a method signature and make it a compiler error when you miss an option:
Really though this would be little more than a syntax suggestion for #486 at that point. |
Beta Was this translation helpful? Give feedback.
-
That code looks perfectly readable to me. |
Beta Was this translation helpful? Give feedback.
-
Or heck, if you don't want the clutter in the class, just use local functions. :) |
Beta Was this translation helpful? Give feedback.
-
I don't like this approach because i have no idea what it means. For example, say i have this: class Base
{
public virtual void DoSomething(Shape s) when s.Area > 10 { ... }
}
class Derived
{
public override void DoSomething(Circle c) when c.Radius > 20 { ... }
} What on earth does this mean? Types have invariance/covariance/contravariance. I can understand how things would work and which of those sorts of changes would be allowed. I have no idea what it means for this pattern restriction to be part of the signature of this method. I also have no idea how this would work for metadata. So you have two |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Ok, I was wrong. I'm trying to solve this problem. The only thing I can think of is priority, but I don't like it. [Priority(1)]
public void DoSomething(Shape s) when s is Circle && s.Area > 10 { ... }
[Priority(2)]
public void DoSomething(Shape s) when s is Circle && s.Radius > 20 { ... } Or something like that: public void DoSomething(Shape s) when 1: s is Circle && s.Area > 10 { ... }
public void DoSomething(Shape s) when 2: s is Circle && s.Radius > 20 { ... } |
Beta Was this translation helpful? Give feedback.
-
Honestly, this would mean that you can't use the same class more than once which to I think really defeats the point. Also, I'm sure having prorities for overloading has been denied before and I bet if they are added, they'll become a code smell right away. C# hasn't needed it up until now and I don't think it should |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi, guys! What do you think about combination of pattern matching and method overloading?
Some example:
Beta Was this translation helpful? Give feedback.
All reactions