-
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
Proposal: in-set and in-range operator to ease checking of value within a pre-defined set #420
Comments
I don't think I like the For the sequence case, what about this? if (('a', 'b', 'c').Contains(someVariable)) It's short, efficient, fairly consistent with the existing LINQ syntax, and requires only a adding an extension method (so you could even implement it yourself). For the range case, what makes syntactic sugar better than creating a |
@svick The problem is solvable with extension methods, but iterating over a sequence may not be desirable because of overheads of involving LINQ in these simplest cases. With the proposed solution, it wouldn't boil down to iterators but to a bunch of inline if == checks. I have seen a couple of similar syntax ideas floating around, and it seems all of them rely on some kind of special case thinking. e.g. |
I guess I wasn't clear: my suggestion was to use a tuple. "Iterating" over that should not have any significant overhead: no iterators, no allocations, no virtual calls (at least for value types, I think). The implementation could look like this: static bool Contains<T>(this (T, T, T) tuple, T value) =>
Equals(value, tuple.Item1) ||
Equals(value, tuple.Item2) ||
Equals(value, tuple.Item3); (Obviously you would also need overloads for number of items other than three.)
That's exactly what a |
@svick Ah, OK. I didn't think of the tuples solution. I was presuming that writing |
Usage:
|
@nesteruk with current c# compiler and jit method with params always allocates an array when you call it. So using params is a bad bad idea. |
@wanton7 I am 100% OK with the compiler allocating an array here. |
@wanton7 So what you do is the same thing you do for string.Format: offer more specific overloads with the most common number of parameters. |
@jnm2 that would work. |
This is effectively a duplicate of #316. And, just like with that proposal, such requests are examples of use cases that could be covered by active patterns. The active pattern proposal covers these scenarios and many more: public bool InPattern<T>(this IEnumerable<T> collection, T matchValue) =>
collection.Contains(matchValue);
public bool InRangePattern<T>(this T value, T minValue, T maxValue) where T : IComparable =>
value.CompareTo(minValue) >= 0 && value.CompareTo(maxValue) <= 0;
...
if(someVariable is In('a', 'b', 'c')) {}
if(someVariable is InRange(1..5)) {} |
Maybe I'm missing some parsing aspect, but what's wrong with simply writing this: if (x in (1, 2, 3)) {} which would be lowered to if (x == 1 || x == 2 || x == 3) {} ? |
#4108 would cover ranges perfectly: if (1 < x <= 9) {} |
In C# 9, you can do |
Can Collection Expressions enable something like this? |
Sometimes when checking if a variable falls within a pre-define set of values there can be a lot of verbosity:
it would be nice if this could be shorthanded to something like:
There are, of course, many ways of going about this already, such as IEnumerable.Contains, but sometimes we don't want to create sequences.
Also, sometimes we want to check for a variable within range:
this could be shortened to:
These would of course work on anything that is IComparable, as above would for anything that is IEquatable. It would simply be syntactic sugar.
The argument can be made about inclusion and exclusion of the last element in range, same as with Ranges. That part of syntax would potentially be the same in both places.
The difference between this and ranges is that Ranges would be a data type and this would be only syntactic sugar. The goal here is not to create another array and enumerate over it.
For example, the example in related #330 would look like:
Related, but not the same: #316 . Difference: in without a set already assumes a sequence follows. Having set here serves to explicitly denote a finite set which is translated into individual checks.
The text was updated successfully, but these errors were encountered: