我觉得我很难找到一个相当简单的方法.
我想我们都用过这个:
select someThing from someTable where someColumn in('item1', 'item2')
Run Code Online (Sandbox Code Playgroud)
在C#中,我必须写这样的东西:
if (someEnum == someEnum.Enum1 || someEnum == someEnum.Enum2 ||
someEnum == someEnum.Enum3)
{
this.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
这有效,但它只是罗嗦.
出于沮丧,我写了一个扩展方法来完成我想要做的事情.
namespace System
{
public static class SystemExtensions
{
public static bool In<T>(this T needle, params T[] haystack)
{
return haystack.Contains(needle);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以编写更短的代码:
if (someEnum.In(someEnum.Enum1, someEnum.Enum2, someEnum.Enum3))
this.DoSomething();
if (someInt.In(CONSTANT1, CONSTANT2))
this.DoSomethingElse();
Run Code Online (Sandbox Code Playgroud)
但是,为我在框架中找不到的东西编写自己的方法感觉很脏.
你们大家可以提供的任何帮助都会很棒,谢谢
编辑:感谢大家的深入分析.我想我会继续使用我的In()方法.
没有现有的扩展方法,就像你拥有的那样.让我解释为什么我认为这是(除了明显的"因为它没有指定,实施,测试,记录等"的原因).
基本上,这种实现必然是低效的.从传递给的参数构造数组In(当使用params关键字时发生)是一个O(N)操作并导致无偿的GC压力(来自构造新T[]对象).Contains然后枚举该数组,这意味着你的原始代码在执行时间上增加了一倍以上(而不是通过短路评估的一个部分枚举,你有一个完整的枚举,然后是部分枚举).
引起的阵列结构的GC压力可以略微通过替换来缓解params与从1抽空类型的X参数X重载的扩展方法的版本T,其中X是一些合理的数量...像1-2打.但这并没有改变这样一个事实,即你将X值传递到调用堆栈的新级别,只是为了检查可能少于它们的X(即,它不会消除性能损失,只会减少它).
然后还有另一个问题:如果你打算将这种In扩展方法作为一系列链式||比较的替代品,那么你可能会忽略其他一些东西.有了||,你会得到短路评估; 对于传递给方法的参数,同样不适用.对于枚举,就像在你的例子中,这没关系.但请考虑以下代码:
if (0 == array.Length || 0 == array[0].Length || 0 == array[0][0].Length)
{
// One of the arrays is empty.
}
Run Code Online (Sandbox Code Playgroud)
上面的(奇怪的/坏的 - 仅用于说明)代码不应该抛出IndexOutOfRangeException(它可能抛出一个NullReferenceException,但这与我正在制造的点无关).但是,使用In得非常好的"等效"代码可以:
if (0.In(array.Length, array[0].Length, array[0][0].Length)
{
// This code will only be reached if array[0][0].Length == 0;
// otherwise an exception will be thrown.
}
Run Code Online (Sandbox Code Playgroud)
我不是说你的In扩展想法很糟糕.在大多数情况下,如果使用得当,它可以节省打字,性能/内存成本也不会明显.我只是提出我为什么这种方法不适合作为内置库方法的想法:因为它的成本和限制可能会被误解,导致过度使用和次优代码.