c# - 内联 HashSet<> 声明与静态属性,.Contains() 性能

标签 c# c#-4.0 hashset

为了使用 Contains 方法,更好的是(有什么区别),用 HashSet 声明一个静态字段或将其声明为内联 (new HashSet { SomeEnum.SomeValue1, SomeEnum.SomeValue2, ... }.Contains(SomeEnum .SomeValue1))

我这么问是因为在某些情况下我只会使用一次哈希集,对我来说最好将它放在代码中而不是某些静态属性中

内联示例(我想使用的):

public void Validate(Type type) {
    if(!new HashSet<Type> { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 }.Contains(type)) {
        //do something
    }
    if(new HashSet<Type> { Type.TYPE_2, Type.TYPE_3, Type.TYPE_4, Type.TYPE_5 }.Contains(type)) {
        //do something
    }
}

静态示例(我不喜欢使用):

private static HashSet<Type> _values1 = new HashSet<Type> { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 };
private static HashSet<Type> _values2 = new HashSet<Type> { Type.TYPE_2, Type.TYPE_3, Type.TYPE_4, Type.TYPE_5 };
public void Validate(Type type) {
    if(!_values1.Contains(type)) {
        //do something
    }
    if(_values2.Contains(type)) {
        //do something
    }
}

使用逻辑表达式的示例(我不想使用的):

public void Validate(Type type) {
    if(type != Type.TYPE_1 && type != Type.TYPE_2 && type != Type.TYPE_3 && type != Type.TYPE_4) {
        //do something
    }
    if(type == Type.TYPE_2 || type == Type.TYPE_3 || type == Type.TYPE_4 || type == Type.TYPE_5) {
        //do something
    }
}

最佳答案

如果您没有通过性能测试将其识别为瓶颈,那么“正确”的方法就是使用对阅读它的人来说最有意义的代码。这有点主观,所以可能没有“正确”的方法,但任何不容易理解的方法都将是“错误”的方法。

我可能只会使用内联声明的数组,除非值列表可以在其他方法中重用,或者它太长以至于妨碍读取该方法正在尝试执行的操作。

public void Validate(Type type) {
    if(!new[] { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 }.Contains(type)) {
        //do something
    }
}

如果您已将其确定为明确的性能瓶颈(意味着您可能每秒执行数百万次此检查,那么您可能需要对几种不同的方法进行性能测试,因为正确的答案取决于您尝试匹配的集合中有多少项。

除了您建议的方法之外,这里还有一些其他可能可能更快的方法(但同样,您需要测试它们以确保:

标志枚举

看起来您正在使用枚举值。如果该枚举类型具有少量潜在值,您可以将其放入标志枚举中,然后使用按位逻辑在单个 CPU 操作中确定给定值是否与您正在查找的任何值相匹配。

[Flags]
public enum Type
{
    TYPE_1 = 1,
    TYPE_2 = 1<<1,
    TYPE_3 = 1<<2,
    TYPE_4 = 1<<3,
    TYPE_5 = 1<<4,
    // etc...
}

用法:

const Type toMatch = (Type.TYPE_1 | Type.TYPE_2 | Type.TYPE_3 | Type.TYPE_4);
if((type & toMatch) == 0)
{
    // do something
}

Switch 语句

编译器非常擅长找出最快的方法,因此如果您使用 switch 语句,它可以决定是否将其编译为一系列 if/else 检查、HashSet 样式的方法或跳转表,具体取决于您要检查的项目的数量和值。

switch(type)
{
    case Type.TYPE_1:
    case Type.TYPE_2:
    case Type.TYPE_3:
    case Type.TYPE_4:
        break;
    default:
        // do something
        break;
}

关于c# - 内联 HashSet<> 声明与静态属性,.Contains() 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19796109/

相关文章:

c# - 如何使用 sqlite-net 在适用于所有数据库模型的父类中实现插入、更新和删除?

c# - 使用正则表达式解析签名,具有 "fun"和数组返回值

c# - 从内存中卸载 DLL

java - 在 TreeSet O(1) 时间内获取最大元素?

如果修改了包含的元素,则 Java HashSet 包含重复项

c# - Log4net 缓冲区大小不起作用

c# - 如何在服务器 app.config 中保存动态端点?

c# - 如何为 Microsoft 的 .NET 4 C# 编译器指定 .NET 版本?

c# - ORA-12557 TNS :protocol adapter not loadable

java - 从 csv 文件中删除重复行而不写入新文件