C#In()方法?(如Sql)

C#In()方法?(如Sql),c#,.net,enums,C#,.net,Enums,我觉得很难找到一个简单的方法 我想我们都用过这个: select someThing from someTable where someColumn in('item1', 'item2') 在C#中,我必须写这样的东西: if (someEnum == someEnum.Enum1 || someEnum == someEnum.Enum2 || someEnum == someEnum.Enum3) { this.DoSomething(); } 这行得通,但太罗嗦了 出于沮丧

我觉得很难找到一个简单的方法

我想我们都用过这个:

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);
        }
    }
}
然而,为我在框架中找不到的东西编写自己的方法感觉很糟糕

你们能提供的任何帮助都会很好, 谢谢


编辑:感谢大家的深入分析。我想我会继续使用In()方法。

如果您想特别对枚举执行此操作,您可能会对该方法感兴趣。

语言不能让每个人都满意,但无论是您还是编译器执行此操作,都没有多大区别。语言给你,


在您的世界中,In可能很好,但当其他人必须提取您的代码时,这将使他们感到困惑。

我认为您已接近使用
包含的调用

List<strong> items = List<string>{ "item1", "item2", "item3" };
bool containsItem = items.Contains( "item2" );

顺便说一句:我喜欢你的扩展方法,我认为它在某些情况下非常有用。

就是这样。您的
In()
扩展方法非常好。即使您使用的是LINQ,它是按照SQL建模的,您仍然必须使用
Contains
来指示在SQL中使用
IN

from a in table
where SomeArray.Contains(a.id)
select a;
翻译为:

select * from table a where a.id in (.....)

我什么都不知道

对我来说,我认为编写这样的扩展方法是可以的,因为您经常需要这样的操作,并且您需要一个可读且方便的语法。这就是扩展方法的好处

这里只有数百种有用的扩展方法。您可能会问,为什么它们不包括在.NET框架中


并非所有内容都可以包含在一种语言中。因此,请编写您自己的库,并希望将来会包含它。

您可以做一些更好的事情,通过使用表达式,这将允许在Linq2Sql之类的情况下正确使用该构造。

如果希望返回不同的值,您可以使用.Intersect扩展方法。例如

List<string> test = new List<string>() { "1", "2", "2", "3" };
List<string> test2 = new List<string>() { "1", "2" };

var results = test.Intersect<string>(test2);
List test=newlist(){“1”、“2”、“2”、“3”};
List test2=新列表(){“1”,“2”};
var结果=test.Intersect(test2);

没有像您现有的扩展方法那样的现有扩展方法。让我解释一下为什么我认为这是(除了明显的“因为它没有被指定、实现、测试、记录等等”原因)

基本上,这种实现必然是低效的。从传递给
中的
的参数构造数组(使用
params
关键字时发生的情况)是一个O(N)操作,并会导致不必要的GC压力(从构造新的
T[]
对象)
包含
然后在该数组上枚举,这意味着您的原始代码在执行时间上增加了一倍以上(不是通过短路求值进行一次部分枚举,而是先进行一次完整枚举,然后进行部分枚举)

通过将扩展方法的
params
版本替换为X重载,从1到X个
T
类型的参数,可以在一定程度上缓解阵列结构造成的GC压力,其中X是一些合理的数字。。。大概12打。但这并没有改变这样一个事实,即您将X值传递到调用堆栈的新级别,只是为了检查可能少于X的值(即,它不会消除性能损失,只会降低性能损失)

然后还有另一个问题:如果您打算在
扩展方法中使用这个
来替代一堆链式的
|
比较,那么您可能忽略了其他一些东西。使用
| |
,您将得到短路评估;对于传递给方法的参数,情况并非如此。对于枚举,就像在您的示例中一样,这并不重要。但是请考虑这个代码:

if (0 == array.Length || 0 == array[0].Length || 0 == array[0][0].Length)
{
    // One of the arrays is empty.
}
上面的代码(怪异/糟糕——仅用于说明)不应该抛出一个
索引自动失效异常
(它可能抛出一个
NullReferenceException
,但这与我的观点无关)。但是,在
中使用
的“等效”代码可以:

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.
}

我并不是说你在
扩展中的
想法不好。在大多数情况下,如果使用得当,它可以节省打字时间,而且性能/内存成本不会太大。我只是想谈谈为什么这类方法不适合作为内置库方法:因为它的成本和限制可能会被误解,导致过度使用和次优代码。

他在扩展方法中使用了Contains。框架中没有专门做这方面的内容,所以你的方法似乎是合理的。如果您不想使用扩展方法,也可以使用新的[]{someEnum.Enum1,someEnum.Enum2}.Contains(someEnum})。虽然扩展方法让它读起来更好。我通常对In查询使用
Contains()
扩展方法。事实上,
Contains()
在Linq to SQL查询中转换为
。我喜欢您的
()
extension方法,因为它为
Contains()提供了很好的语法包装
在我还没有可枚举容器中的值时使用。看起来你基本上明白了为什么扩展方法会在那里。我喜欢你方法的简洁。除了扩展方法很好之外,我还对你在系统名称空间中包含它的方式感到有趣,而s避免在所有使用它的地方都包含自定义名称空间,有些人可能会反对将代码添加到系统名称空间。我建议您在in方法中添加具有不同参数计数的重载,以防止在使用很少参数时分配数组。@leppie框架在ToString impl中使用此属性枚举器不匹配任何值时枚举的校正,
if (0 == array.Length || 0 == array[0].Length || 0 == array[0][0].Length)
{
    // One of the arrays is empty.
}
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.
}