为了使用Contains方法,更好的(有什么区别),用HashSet声明一个静态字段或将其声明为内联(new HashSet {SomeEnum.SomeValue1,SomeEnum.SomeValue2,...} .Contains(SomeEnum) .SomeValue1))
我问这是因为在某些情况下我只会使用一次hashset,对我来说最好是在代码上而不是在某些静态属性中
示例内联(我想要使用的内容):
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
}
}
答案 0 :(得分:2)
如果您还没有通过性能测试将其识别为瓶颈,那么“正确”的方法就是使用对人们来说最有意义的代码。这有点主观,所以可能没有“正确”的方式,但任何不容易理解的方法都是“错误的”方式。
我可能只是使用内联声明的数组,除非值列表在其他方法中可重用,或者它很长,以至于它妨碍了读取方法尝试做的事情。
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语句,它可以决定是否将其编译为一系列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;
}
答案 1 :(得分:0)
如果不添加新项目,那么静态方法是正确的方法
private static HashSet<Type> _values = new HashSet<Type> { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 };
public void Validate(Type type) {
if(!_values.Contains(type)) {
//do something
}
}
System.Collections
命名空间中的所有集合都是线程安全的for read only operations,因此这是一种完全可以接受的方法。
如果你以“首选”的方式做到这一点它仍然可以工作,但是你每次调用函数时都会重新创建集合,这是一个不必要的开销,肯定会损害性能。
答案 2 :(得分:0)
正如文章暗示的那样,记住查找的“偶尔”或“一次”使用情况。
如果查找仅在单个方法中使用,那么我将使用内联方法,但是我会使用数组(我实际上经常这样做)。我可能会或可能不会使用中间(本地)变量,具体取决于我是否使代码更清晰或更容易适应未来。
我不会使用静态(甚至是实例)变量,因为:
如果我想在多个方法之间共享此查找,我会考虑创建一个返回 new 对象的getter(在满足新要求时覆盖#2和#3)。使用局部变量,单个方法每次调用只会创建一个新的查找。
我通常使用数组,因为:
如果它使特定代码更难以遵循,我不会使用各种长手形式。任务是“包含”,而不是一些更复杂的条件逻辑。
除非存在实际的性能问题,否则请使用干净简单的方式继续执行更多有趣的任务。