I'm having a hard time finding what, I think, should be a fairly simple method.
I think we've all used this:
select someThing from someTable where someColumn in('item1', 'item2')
In C#, I've have to write stuff like this:
if (someEnum == someEnum.Enum1 || someEnum == someEnum.Enum2 ||
someEnum == someEnum.Enum3)
This works, but it's just wordy.
Out of frustration, I wrote an extension method to accomplish what I'm trying to do.
public static class SystemExtensions
public static bool In<T>(this T needle, params T haystack)
Now, I can write shorter code:
if (someEnum.In(someEnum.Enum1, someEnum.Enum2, someEnum.Enum3))
if (someInt.In(CONSTANT1, CONSTANT2))
It feels dirty, however, to write my own method for something that I just can't find in the framework.
Any help you folks can offer would be great,
EDIT: Thanks everyone for the in-depth anaylsis. I think I'll keep using my In() method.
There's no existing extension method like what you have. Let me explain why I think that is (aside from the obvious "because it wasn't specified, implemented, tested, documented, etc." reason).
Basically, this implementation is necessarily inefficient. Constructing an array from the parameters passed to
In (as happens when you use the
params keyword) is an O(N) operation and causes gratuitous GC pressure (from the construction of a new
Contains then enumerates over that array, which means your original code has been more than doubled in execution time (instead of one partial enumeration via short-circuited evaluation, you've got one full enumeration followed by a partial enumeration).
The GC pressure caused by the array construction could be alleviated somewhat by replacing the
params version of the extension method with X overloads taking from 1 to X parameters of type
T where X is some reasonable number... like 1-2 dozen. But this does not change the fact that you're passing X values onto a new level of the call stack only to check potentially less than X of them (i.e., it does not eliminate the performance penalty, only reduces it).
And then there's another issue: if you intend for this
In extension method to serve as a replacement for a bunch of chained
|| comparisons, there's something else you might be overlooking. With
||, you get short-circuited evaluation; the same doesn't hold for parameters passed to methods. In the case of an enum, like in your example, this doesn't matter. But consider this code:
if (0 == array.Length || 0 == array.Length || 0 == array.Length)
// One of the arrays is empty.
The above (weird/bad -- for illustration only) code should not throw an
IndexOutOfRangeException (it could throw a
NullReferenceException, but that's irrelevant to the point I'm making). However, the "equivalent" code using
In very well could:
if (0.In(array.Length, array.Length, array.Length)
// This code will only be reached if array.Length == 0;
// otherwise an exception will be thrown.
I'm not saying your
In extension idea is a bad one. In most cases, where used properly, it can save on typing and the performance/memory cost will not be noticeable. I'm just offering my thoughts on why a method of this sort would not be appropriate as a built-in library method: because its costs and limitations would likely be misunderstood, leading to over-use and suboptimal code.