-
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
returnif, breakif and continueif #2261
Comments
Should the language have a thousand different keywords, so that you never need to type anything? Replace every single common pattern with a keyword? The language gives useful building blocks with which it is possible to express almost any logic you want. Adding in keywords willy nilly to save a line of code just increases the cognitive complexity of the language, and the complexity of implementing it. |
You can already write that as:
There appears to be almost no value added by these proposals. |
Your use of |
@CyrusNajmabadi |
You can already write this as: var t = CheckToolStrip(c as ToolStrip);
if (t != null)
return t;
t = CheckToolStrip(c.ContextMenuStrip);
if (t != null)
return t;
t = CheckControls(c);
if (t != null)
return t; like so: var t = CheckToolStrip(c as ToolStrip) ?? CheckToolStrip(c.ContextMenuStrip) ?? CheckControls(c);
if (t != null)
return t; You are writing out code that is more compelx than necessary, not using available mechanisms to shorten things, and then asking for new features to replace the ones already there. |
addressed here: #2261 (comment) |
@MohammadHamdyGhanem Instead of: for (int i = 0; i<N; i++)
{
returnif Find(i);
} Why not |
ToolStripItem CheckControls(Control parent)
{
foreach (Control c in parent.Controls)
{
if (c.Visible)
returnif (CheckToolStrip(c as ToolStrip),
CheckToolStrip(c.ContextMenuStrip),
CheckControls(c));
}
return null;
} You can already write the above more simply as: return parent.Controls.OfType<Control>()
.Where(c => c.IsVisible)
.Select(c => CheckToolStrip(c as ToolStrip) ??
CheckToolStrip(c.ContextMenuStrip) ??
CheckControls(c))
.WhereNotNull()
.FirstOrDefault(); The code i wrote is possible today, and is 7 lines to the 9 lines your feature would offer. You don't need new language features for brevity. You need to use the features the language already provides you. |
@CyrusNajmabadi By the way, LinQ expressions can be complex and less readable and harder to understand, so it is not always a good thing to write each procedure as a LinQ query! |
Because it's a trivial method you can write in 10 seconds.
I see nothing about your code that is more readable than this simple linq expression which has been supported in the language for nearly 15 years at this point. Also, this is not a linq quesry. it's just bog standard method calls with lamdbas. Bread and butter of C# for ages. Adding more and more syntax to replace what can be trivially done with existing features is not great... |
.WhereNotNull() It's just my shortcut for writing |
Who needs a .FirstOrDefault(c => c != null); |
It don't exist in BCL (yet?) but you can write it yourself anytime |
As of C# 8, example 2 can be expressed as: ToolStripItem? CheckControls(Control parent)
{
foreach (Control c in parent.Controls)
{
if (c.Visible &&
(CheckToolStrip(c as ToolStrip) ??
CheckToolStrip(c.ContextMenuStrip) ??
CheckControls(c)) is {} t)
{
return t;
}
}
return null;
} I therefore see no use for a |
While you're probably right, this makes it even worse because we would assume it's a boolean. It also great limits the use case when he could've made the function return true or false or do a |
Instead of the proposed returnif, breakif and continueif, which all have an extremely narrow focus based on null values, I'd prefer to see something more flexible and generally useful. What about reusing the existing The first example from the OP would become ... for (int i = 0; i < N; i++)
{
return Find(i) when (value != null);
} Example 2 from the OP: ToolStripItem CheckControls(Control parent)
{
foreach (Control c in parent.Controls)
{
if (c.Visible)
{
return CheckToolStrip(c as ToolStrip) when (value != null);
return CheckToolStrip(c.ContextMenuStrip) when (value != null);
return CheckControls(c) when (value != null);
}
}
return null;
} The advantage of this syntax is that the condition isn't hidden - even better, the dev has a choice of condition and doesn't have to contort things. Though, having written this up ... while this is better (more generally useful) than the original suggestion ... I do not think adding optional |
@theunrepentantgeek |
Very, very, little. 😀 Perhaps that it more naturally sits on one line ... perhaps. |
@theunrepentantgeek for (int i = 0; i < N; i++)
{
if ((var r = Find(i)) != null)
return r;
} It is still longer, but saves one line, and it will be valid as soon as C# allows to declare variables inside any
The rulse are simple:
So, my suggestion achives your aim with minimal syntax. |
This doesn't seem like a problem.
You could save all lines if you just added I think you overly obsess over taking each and every bit of code you write, and trying to make it into a single line. You do this in many different issues, and you commonly ignore existing constructs that will simplify your code, asking for new constructs instead because you just don't like something about the existing constructs. This isn't a tenable way to do language design. We can't just add lots of orthogonal features to improve things, have them ignored, and then have proposals taht are much more limited in scope just because you won't use the existing features.
This very much goes against hte spirit of C#. We do not have flow control operators that are interchangeable over bools and nulls. Indeed, it's been explicit to not do this due to the common concern about bugs creeping in this way. This would not be done without a major philosophical shift in the language. And if that were to happen, you'd see it first in cases like |
@MohammadHamdyGhanem, You code example, for (int i = 0; i < N; i++)
{
if ((var r = Find(i)) != null)
return r;
} is already valid in C# 8, just with slightly different syntax: for (int i = 0; i < N; i++)
{
if (Find(i) is {} r)
return r;
} So it still remains unclear to me as to what you are really wanting here. |
@DavidArno |
You can write that. But that will not have the |
Again, this is what i was saying above. You are not using the actual facilities given in hte language, and are asking for new language features to implement a more limited form of functionality. |
Why is it strange?
You save one character. All to do something the language can already do today. at this point, these proposals just seem like spam. You avoid the features the language has, and you continually propose alternate ways to just do the exact same thing, but with barely any saving (if any) at all.
Please try to learn all the language has to offer. You might find you need far less changes in it if you didn't continuously try to not learn about and not use what is already there. :-/ |
@CyrusNajmabadi |
it means |
It has meaning.
Of course. "Call
None of
No.
No.
No.
Why? It's a normal way of saying something.
You keep asking for features that replicate feature the language already has just because you don't want to use them. This isn't going to happen. |
This is what the compiler does, not what the symbols say in a clear way. Where can I get the non-null meaning in this statement? Empty brackets do give the impression of a null! maybe |
And I want to say, that some features staring with multi-line lambdas and local functions complicated the language and make the syntax insane! One can define a local function inside a lambda inside a function, which yields a complex code structure that is hard to comprehend. Why does anyone do that? because he can and C# allows him to! |
It all becomes clear when you're used to it. The The two following patterns do the same thing: if (Find(i) is Foo r) return r;
if (Find(i) is {} r) return r; Here's an example of a property pattern being used recursively: string name = ...;
if (name is { Length: var length }) Console.WriteLine($"The name is {length} characters long."); |
By the way: One thing is missing to reach the full lambda complexity: allow recursive lambdas :D Note: Func<int, int> foo=
x =>
(x <= 1)? 1 : x; |
@HaloFour |
@MohammadHamdyGhanem
done: Func<int, int> Factorial = null;
Factorial = x => (x <= 1)? 1 : x * Factorial(x-1); The problem has nothing to do with lambdas, an unassigned variable cannot reference itself. Local functions may invoke themselves recursively. |
@HaloFour |
The same place you get the non-null meaning when someone writes: In C#
But you just suggested a large set of unusual symbol that would make the language harder to learn for beginners. Why do these rules you state not apply to your own suggestions? As i already showed (for example here, your features do not fit in with rules that C# has followed since inception. By adding them, you make the language less consistent and harder to learn. -- The part you seem to be missing is that C# has added patterns. One way patterns are surface is like so:
Once you know that, then it becomes easy to figure out what's going on. After the |
I don't like this idea. The reason I'm posting this comment is that the author doesn't seem to care about arguments against his proposal, maybe seeing the number of people that disagree with him will have more of an effect. By the way, if in some alternate universe this somehow gets implemented, I also want P.S. Don't mean to be cynical, just think it sounds funny. |
@TKharaishvili |
Closing as OP no longer has an account on github, and this suggestion was fairly poorly received. |
I suggest to add conditional terminate statements say:
returnif
,breakif
andcontinueif
Or
return??
,break??
andcontinue??
Syntax:
returnif Expr1;
returnif (Expr1, Expr2,....., ExprN);
These conditional terminate statements will be executed only if one of the expressions is true or is not null.
Use case:
This is a shortcut for
Example 2:
Would be:
The text was updated successfully, but these errors were encountered: