-
Notifications
You must be signed in to change notification settings - Fork 1k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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: C# Break nested loop #869
Comments
@Danthekilla, You forgot the existing third way: (bool found, ValueType value) Foo()
{
for (int x = 0; x < xMax; x++)
{
for (int y = 0; y < yMax; y++)
{
var foundValue = GetValue(x, y);
if (foundValue == valueToCompare) return (true, foundValue);
}
}
return (false, default);
} Small focused functions are your friend. But if you want long functions, as you say, there is already two ways of achieving this goal. So I'd see yet another way of achieving it as really bringing nothing to the language. |
Sometimes it's a loop and a switch and coming up with a name for it is super arbitrary and counter-intuitive. |
I'm not in favour of this but I think the following is better
|
I'd prefer to see something like Java Branching Statements, as once pointed out by @HaloFour at #176 (comment) |
|
@Logerfo, Indeed, it makes things clear than having something like |
Inline returns slow down loops until .NET Core 2.1 dotnet/coreclr#13314 and functions with a loop generally won't inline (without forcing); so wouldn't be so great for very hot loops; though ok for general loops. |
|
@bondsbw Not to mention copy/paste. |
This is simple, short and elegant. Goto's require maintenance and their excessive use results in spaghetti code. Extra temp variables hanging around is just junk code that can go wrong. Break = n; in an n deep loop would create short, concise code that cannot be confused for anything else. |
I agree with some of the other posters, I don't like the use of an integer indicating the number of levels. If any enhancements to String foundValue = null;
OUTERLOOP:
for (int x = 0; x < xMax; x++)
{
for (int y = 0; y < yMax; y++)
{
foundValue = GetValue(x, y);
if (foundValue == valueToCompare)
break OUTERLOOP;
}
} This makes it much clearer exactly where the |
I agree that breaking from a named loop is the best option. I think there was a proposal of mine asking for that. Or was it left in the roslyn repo? |
@jnm2 It's better to have an "arbitrary" label and know what it is than having a number and starting to wonder what it means, sometimes. |
@eyalsk Exactly my point. 😄 |
@eyalsk I don't remember preferring numbers but I'm happy to update my opinion if I did write that somewhere. I'm not seeing it. |
@jnm2 I was referring to this comment.
Anyway, deleted my comment. p.s. I might misinterpreting your comment. |
Ah, I was answering @DavidArno who suggested that you refactor it into a separate method which would then need a name. It did not escape me that you also need a name for a label, but it the label name is free to be coupled to only make sense in the context of the control flow in the method's implementation whereas refactoring it to a separate method requires it to arbitrarily stand on its own when that was never its purpose. |
@jnm2 got'cha. 😉 |
@jnm2 Doesn't that change when you use a local function instead of a method? I think that the name of a label and the name of a local function can both be specific to a single method, or even to a scope within a method. |
In theory. That's a good point. |
Personally I find that coming up with a name for a goto can be very arbitrary and quite counter-intuitive. Which is why I would prefer to use a 'break integer' syntax, it seems cleaner and more readable to me. Refactoring tools like resharper should be able to support it fairly easily, I don't think refactoring would be much of an issue. |
Already today a goto label name like |
@Danthekilla
Yes, naming is hard, we all know that but just like we come up with names that make sense for other things throughout the code we should do the same here. goto:
break:
Readable code should be easy to follow and understand so doing something like p.s. Both Java and JavaScript allows having labels on break and continue so having this in C# would come in handy at times. |
(bool found, ValueType value) TryFindValueIn2DStructure(... I've never really been convinced by the "naming is hard" argument. If you understand what a piece of code does, you can describe it. If you can describe it, you can summarise it. That summary gives you the name. If the summary is long (and likely contains lots of and's or then's), then it's probably doing too much and could do with breaking into smaller parts. |
@DavidArno "naming is hard" because thinking about it objectively is indeed hard, different people may have different opinions about how something should be named and it's even harder for a name to make sense outside to the few lines of code you or someone else wrote and last but not least code tend to change over time and name things so everything will make sense all of the time, especially the future isn't that simple. |
I agree with @DavidArno, if you have a need to break from a loop then you have a reason for wanting to do so. It shouldn't be that difficult to summarize that into a quick one or two word label, e.g. |
I am definitely not a fan of introducing a more restrictive lang feature just because someone thinks the existing capability is too permissive. If the feeling is that something is too permissive, then that much better solved with an analyzer vs adding an entire new feature to just provide a subset of existing functionality. |
Interesting, I look at the code and when I see
But nobody takes away the "Why take this feature away just because someone thinks it's unnecessary for him?" |
? My argument is the opposite. We already have a permissive feature, so we shouldn't create restrictive features to duplicate them. You can just use an analyzer if you don't like the idea of having non-loop code follow the goto.
Right... that's my point. Since goto works well for this, and is already tehre, and already supports a superset of this functionality with great syntax, i would stick with it. If that superset is not desirable, i would recommend using an analyzer versus just creating a duplicated feature here. |
I get teh ask. I'm just saying i don't think it carries its weight given the ease of writing 'goto' (which still seems great here and very readable to me). |
You write your code basically once, but you maintain it for a long time -- it means you read it more then you write it. So it is crucial the code speaks to you in clear fashion -- goto does not have any special meaning, break/continue has. If someone misplace/misuse the label it is harder to find the bug than with break/continue because the latter have extra information embedded in them -- they are telling the reader the meaning. Or, shorter version, goto was from the beginning, so why we have break/continue in the first place, if we could live just with goto? |
I mean, it means: go to this label :)
What sort of misuse are you thinking of? If you're worried about placement, that ties into what i was saying above, just add an analyzer to restrict to only teh stylistic uses of goto you're comfortable with.
Because they don't need labels. If you need labels, at that point, just use 'goto' :) |
@CyrusNajmabadi Sorry, non-English, confused restrictive with permissive :) But how would you write an analyzer that knows if you want to Also I've written so far 2 super simple analyzers and I don't expect majority of people invest time to learn Roslyn "just for this". |
Would it be better to use keywords instead of labels? while(...)
{
while(...)
{
break outer;
while(...)
{
break outer outer;
}
}
} |
@TahirAhmadov what if someone adds another loop? He would have to remember to add another |
If you want that, then there's no problem at all as this is the style you like so nothing to worry about. The analyzer is for people that don't like general goto, but are ok using it in a loop. |
The majority of people don't need to do this. Someone just needs to write it once and make into a nuget package. If users want this sort of linting, they can choose to use that package. If htey don't care, then there's no issue :) If users care, but not a single person cares enough to write an analzyer, then it sounds like there isn't much caring after all, in which case i'd def believe there's not a great reason to make this into a lang feature. |
But still, analyzer would solve an issue for people who don't like Also this still wouldn't solve the readability issue, which.. for you is fine, but I would definitely see the loop labels more readable, especially for more complex code than 5 line example. |
I'm still not sure why it's safer tbh.
Maybe say that if a goto is in a loop, it needs to be at the end of the loop. If you want inner gotos and loop gotos, then you have to decide what you want. |
People, including me, have already written their opinions on why
You see, analyzer doesn't solve everything this feature would solve. You would have to have either one or the other, not both. |
I don't really get your argument. All you said was: "Interesting, I look at the code and when I see continue inner, I immediately know it means the inner loop should continue." You can't know that. You have to go figure that out. For example, the code coudl have said: inner: foreach (...) {
outer: foreach (...) { now, the Labeling this explicitly and then stating you want to go there makes the most sense to me and actually fits what the language is doing here. It was also so much clearer in the code you had in your example. Indeed with your example code it was much more confusing as now i had to say "oh... i have to be careful if someone goto's this location, as opposed to 'continue'ing to it".
If the cases it doesn't solve are so niche, then that's not something that makes me want to add this feature. If the only reason to have htis feature is so that a subset of users can mix-match gotos and continues/breaks in a loop and have differing semantics for them, then that's so minor that i don't think it's warranted as a language feature. |
I also said this:
With the Unlike the Now you can say "so what?" and I agree that this is not a critical feature that the majority of C# programmers will use, but why not have it for the rest? Other languages have it and I'm sure it has it's users. For example Golang is "fairly new" and has both |
This ignores the fact that GOTO is so permissive that it's use has been banned from the code bases of the last 4 places I have worked at. GOTO and its use is very frowned upon, for many codebases this would be a cleaner replacement, but I understand the downsides too. That being said I find it amusing you are all still discussing this issue 5 years after I first submitted the proposal 😂 |
Well, I'm here too, and this topic is even 'more or less' the continuation from the old visual studio forum, so it's more than 5 years. We are programmers, not kids, if the goto is good or bad to the code should be the programmer should decide this. C# is a high level language, so It should aim to simplify the programmer's life where It can, as such I find this feature interesting, and frankly, having to fill the recursive loops relating to the previous loop with booleans and ifs, in my opinion is what makes confusing code, many cases where the code continuation point could be executed where it was necessary to decide where it needs to continue could be solved with this, instead of creating new variables and ifs to check every each loop. |
@NigelBess wrote:
and @leoshusar responded:
then @marcussacana wrote:
There's a fallacy here - even a moderate sized project (say, 200kloc) will have multiple developers and maintainers and a lifespan measured in years. If even one of those developers uses a particular C# feature, then all of those developers needs to be aware of it, else they'll run into code they cannot reason about. The developer who introduced use of the feature may have retired and be living off the grid in an island paradise by the time a new developer runs into the code. Saying "if people don't like it, they don't have to use it" ignores the reality that most business development involves teams working on a common codebase over several years. |
That's also because you consider that every programmer works for a company without its own code of conduct, |
Why is it frowned upon? |
This was the first result in Google, there are 1000's more. Personally I think it has its uses and banning it from codebases is going to far, but many disagree. |
GOTO in older languages could be very dangerous. It effectively let you jump anywhere, into and out of functions and other protected areas. The version of GOTO in C# has much stricter guardrails, but that stigma from decades ago remains, likely continuing to be drilled into the minds of students by their professors. You can thank Dijkstra for that. |
That is 'goto' in idl. I'm asking why it's frowned upon in c#. |
I recommend the use of
|
Boy do I with MS would introduce labeled loops. It's literally the one totally valid use-case for Apparently new C# feautres need a 'champion'. Well, I'm not sure why nobody seems to be willing to champion this considering I've seen comments from hundreds of developers who want it. I'll also just mark here that a related discussion is going on at #5525 |
Because it's not the C# language team telling people to not use |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
@Danthekilla commented on Thu Aug 31 2017
In C# it would be fanstastic to have a language feature (probably syntactic sugar) that lets you break nested loops.
Currently these are the 2 ways you can break out of nested loops:
I would like to propose the ability for a break to have a value for how many loops to break out of. Like so:
Not only is it slightly smaller, but I think easier to read.
Anyone have any thoughts on the matter?
The text was updated successfully, but these errors were encountered: