Proposal: in-set and in-range operator to ease checking of value within a pre-defined set #8720
Replies: 15 comments 1 reply
-
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 |
Beta Was this translation helpful? Give feedback.
-
@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. |
Beta Was this translation helpful? Give feedback.
-
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 |
Beta Was this translation helpful? Give feedback.
-
@svick Ah, OK. I didn't think of the tuples solution. I was presuming that writing |
Beta Was this translation helpful? Give feedback.
-
Usage:
|
Beta Was this translation helpful? Give feedback.
-
@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. |
Beta Was this translation helpful? Give feedback.
-
@wanton7 I am 100% OK with the compiler allocating an array here. |
Beta Was this translation helpful? Give feedback.
-
@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. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 that would work. |
Beta Was this translation helpful? Give feedback.
-
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)) {} |
Beta Was this translation helpful? Give feedback.
-
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) {} ? |
Beta Was this translation helpful? Give feedback.
-
#4108 would cover ranges perfectly: if (1 < x <= 9) {} |
Beta Was this translation helpful? Give feedback.
-
In C# 9, you can do |
Beta Was this translation helpful? Give feedback.
-
Can Collection Expressions enable something like this? |
Beta Was this translation helpful? Give feedback.
-
I like this proposal but maybe without the
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
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.
Beta Was this translation helpful? Give feedback.
All reactions