我很难找到我认为应该是相当简单的方法。
我想我们都用过这个:
select someThing from someTable where someColumn in('item1', 'item2')
在 C# 中,我必须编写如下内容:
if (someEnum == someEnum.Enum1 || someEnum == someEnum.Enum2 ||
someEnum == someEnum.Enum3)
{
this.DoSomething();
}
这行得通,但太冗长了。
出于沮丧,我写了一个扩展方法来完成我想做的事情。
namespace System
{
public static class SystemExtensions
{
public static bool In<T>(this T needle, params T[] haystack)
{
return haystack.Contains(needle);
}
}
}
现在,我可以写更短的代码了:
if (someEnum.In(someEnum.Enum1, someEnum.Enum2, someEnum.Enum3))
this.DoSomething();
if (someInt.In(CONSTANT1, CONSTANT2))
this.DoSomethingElse();
然而,为我在框架中找不到的东西编写自己的方法感觉很脏。
如果你们能提供任何帮助,那就太好了, 谢谢
编辑:感谢大家的深入分析。我想我会继续使用我的 In() 方法。
最佳答案
没有像您现有的扩展方法。让我解释一下为什么我认为这是(除了明显的“因为它没有指定、实现、测试、记录等”原因之外)。
基本上,这种实现必然是低效的。从传递给 In
的参数构造一个数组(就像使用 params
关键字时发生的那样)是一个 O(N) 操作并导致不必要的 GC 压力(来自构造一个新的 T[]
对象)。 Contains
然后枚举该数组,这意味着您的原始代码的执行时间增加了一倍多(而不是通过短路评估进行的部分枚举,您有一个完整的枚举,然后是部分枚举枚举)。
通过将扩展方法的 params
版本替换为从 1 到 X 类型的参数的 X 重载,可以在一定程度上减轻数组构造造成的 GC 压力 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.
}
上面(怪异/糟糕——仅供说明)代码不应抛出 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.
}
我并不是说您的 In
扩展想法不好。在大多数情况下,如果使用得当,它可以节省打字时间,并且性能/内存成本不会很明显。我只是就为什么这种方法不适合作为内置库方法提出我的想法:因为它的成本和限制可能会被误解,从而导致过度使用和次优代码。
关于C# In() 方法? (像 SQL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3440539/