Skip to content
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

Bool arguments as switches (similar to PowerShell's switch parameters) #1462

Closed
FurkanKambay opened this issue Apr 16, 2018 · 20 comments
Closed

Comments

@FurkanKambay
Copy link

FurkanKambay commented Apr 16, 2018

Description

When calling a method that takes a bool parameter, if we want to pass in true, instead of using a named argument like Foo(bar: true), we'll be able to use the parameter's name by itself with a prefix (TBD) like Foo(#bar);. (multiple parameters will benefit more)

The decision of the prefix is a part of the discussion.

Optional bonus syntax

When defining a method, instead of using an optional parameter like void Foo(bool bar = false), we'll be able to use the switch keyword like void Foo(switch bar).

Code

The prefix: TBD (currently using #)

Foo(42, bar: true, qux: true);
// to
Foo(42, #bar, #qux);
void Foo(int number, bool bar = false, bool baz = false, bool qux = false)
// to
void Foo(int number, switch bar, switch baz, switch qux)
@FurkanKambay FurkanKambay changed the title Bool Parameters as Switches (similar to PowerShell's switches) Bool arguments as switches (similar to PowerShell's switch parameters) Apr 17, 2018
@bondsbw
Copy link

bondsbw commented Apr 17, 2018

Your example is already valid C#:

void Foo(int a = 0, int b = 0, bool bar = false, bool baz = false) {}
...
int bar = 1, baz = 2;
Foo(+bar, -baz);

@FurkanKambay
Copy link
Author

@bondsbw Sorry about that, I forgot to add that I picked + and - in my examples but they can be other prefixes. I was going to go with : at first, but couldn't think of a false counterpart.

@bondsbw
Copy link

bondsbw commented Apr 17, 2018

I like this concept if we can come up with good, unambiguous syntax. Foo(bar: true, baz: false) is much better for readability than Foo(true, false) but it's also more verbose. Your suggestion is sort of a best of both worlds and could encourage self-documenting code.

@MkazemAkhgary
Copy link

C# has its own syntax. What benefits would this addition provide?

@FurkanKambay
Copy link
Author

FurkanKambay commented Apr 17, 2018

@MkazemAkhgary it will be just a syntactic sugar to make the method call take less space and read better. As @bondsbw said above, it can also encourage self documenting code.

People who gave a thumbs-down, can you explain why? Do you think it's unnecessary, or…? If it's something specific, can it be improved? A constructive comment is better than a bad reaction.

@ufcpp
Copy link

ufcpp commented Apr 17, 2018

It's less necessary but breaks existing codes.

@FurkanKambay
Copy link
Author

@ufcpp How does it break existing codes exactly? It will still compile to what we write today. It's just syntactic sugar. If you mean the + operator, again, the reason I picked it is that I couldn't think of something else.

@theunrepentantgeek
Copy link

APIs evolve over time, and every long lived codebase I've worked on has found that methods with bool parameters (and return types) are a problem to evolve.

Generally speaking, when reviewing code, if I see you have a method taking a single bool, I'll suggest you split it into two methods. For example, I'd suggest Start() and Stop() are better than ConfigureActive(bool).

The TPL method ConfigureAwait(bool) would be better (in my opinion) as ContinueOnCapturedContext() and ContinueOnCurrentContext() because that's what the bool means.

FWIW, I've found method signatures with bool to be such an antipattern that I've blogged about it multiple times:

(Providing the links seems more efficient than rehasing the same old arguments anew; if this is unwelcome in this repo, I'll happily remove them from this comment.)

@ufcpp
Copy link

ufcpp commented Apr 17, 2018

@DavidArno
Copy link

DavidArno commented Apr 17, 2018

@theunrepentantgeek

... if I see you have a method taking a single bool, I'll suggest you split it into two methods...

👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍

@FurkanKambay
Copy link
Author

@ufcpp I already replied to that. The prefix isn't +, that decision is part of the discussion.

@theunrepentantgeek Well, the method can take as many bools as it wants. While I agree with you on your point on single-bool methods, this syntax isn't for just those. I just wrote methods with 1 and 2 parameters just to make it simple to show; my bad if that mislead you.

About your blog posts: 2 of them are for return values so I won't address them because they don't have anything against the proposal. And the first one is basically the same as what you said about splitting single-bool methods. So, the last one:

You're right, that many bool parameters are absurd and using an enum is the correct way to go. But they don't have to be that many parameters. Or even if there were, calling the method with switches would be shorter than using enums, and more readable than true and falses. And the ones that are false will be left out.

I don't know it seems like this way could be a middle ground. It's not that much work, so I thought I'd take a shot. I'm just trying to defend my idea, I'm not sure I make sense 😄

@Joe4evr
Copy link
Contributor

Joe4evr commented Apr 17, 2018

I see you have a method taking a single bool, I'll suggest you split it into two methods

If nothing else, create a [Flags] enum and take that in your method.

@bondsbw
Copy link

bondsbw commented Apr 17, 2018

@Joe4evr

If nothing else, create a [Flags] enum and take that in your method.

That's what I might do today. But we are building a type for the exclusive purpose of being a set of parameters to one method - seems like an anti-pattern in itself.

I don't advocate that in other situations, because method parameters are a good feature of the language. The reason we advocate it with bool parameters is because their meaning tends to get lost more easily when parameter names are hidden, but I welcome ideas to improve on that specific aspect.

@bondsbw
Copy link

bondsbw commented Apr 17, 2018

Backtick is a possible unary operator for this proposal:

Type.GetType(typeName, `throwOnError, `ignoreCase);

@HaloFour
Copy link
Contributor

I like what IntelliJ does here. For opaque arguments like Boolean or String literals the IDE shows the parameter name inline automatically:

image

Doesn't help outside of the IDE, of course.

@bondsbw
Copy link

bondsbw commented Apr 17, 2018

I suggest limiting switch parameters to bool type with default value false.

No need for the void Foo(switch bar) syntax, and it could work with many existing APIs. And no need for a false version of the parameter, it is implied via exclusion.

@FurkanKambay
Copy link
Author

@bondsbw
I proposed the switch syntax just to make parameters shorter. switch foo instead of bool foo = false. When there are multiple parameters, it'll get long. And the current switch is a very different thing, so, there is no conflict. I still stand by this.

You're right about the false version. It's really unnecessary.
And the default value will be false, as you said.

@theunrepentantgeek
Copy link

@FurkanKambay:

I don't know it seems like this way could be a middle ground. It's not that much work, so I thought I'd take a shot. I'm just trying to defend my idea, I'm not sure I make sense 😄

Good on you for taking a shot - the whole idea of this repo is to discuss potential language enhancements. Inevitably, most of them will go nowhere, but all of them will inform the folks in charge of the language about what their users think is important.

@MgSam
Copy link

MgSam commented Apr 18, 2018

@theunrepentantgeek

but all of them will inform the folks in charge of the language about what their users think is important.

If only that were true... :(

@theunrepentantgeek
Copy link

@MgSam I'm convinced it is true. #ymmv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants