C# In() 方法? (像 SQL)

标签 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();
}

这行得通,但太冗长了。

出于沮丧,我写了一个扩展方法来完成我想做的事情。

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/

相关文章:

c# - 无状态状态机框架和高 CPU 使用率

java.sql.SQLException : Data truncated for column 异常

java - 使用枚举的策略模式。需要一个简单的Java示例

C 程序——在编译时检查两个枚举是否同步

c# - 如何获取枚举数?

c# - 如何在 .NET 5.0 控制台应用程序上检查 C# 中的 Windows 版本

c# - 从 MySQL 数据库中过滤数据并在 datagridview 中显示

c# - 检查是否从 C# 的下拉列表中选择了一个值

c# - 如何检查 DateTime 是否发生在今天?

c# - 在带有缩进的文本文件中写入文本(C#代码)