C# 从一组枚举值中选择
我有一个包含一个枚举属性列表的项集合。 原始属性看起来像C# 从一组枚举值中选择,c#,linq,enums,lambda,C#,Linq,Enums,Lambda,我有一个包含一个枚举属性列表的项集合。 原始属性看起来像 public class Content { List<State> States {get; set;} } 如何使用Linq或Lambda实现这一点?您不需要Linq。我不认为 if(item.States.Contains(State.Important) && item.States.Contains(State.Updated)) string toProcess = "Do"; 你不
public class Content {
List<State> States {get; set;}
}
如何使用Linq或Lambda实现这一点?您不需要Linq。我不认为
if(item.States.Contains(State.Important) && item.States.Contains(State.Updated))
string toProcess = "Do";
你不需要林克。我不认为
if(item.States.Contains(State.Important) && item.States.Contains(State.Updated))
string toProcess = "Do";
如果必须使用Linq:
if (item.States.Any(state => state == State.Important) && item.States.Any(state => state == State.Updated))
否则,只需使用@ElRonnoco所说的内容
然而,如果你的州是2的幂,那么这个答案将略有不同
这种方法的问题在于,如果两种状态都没有设置,它会在集合上完全迭代两次。如果这种情况经常发生,它将比可能的要慢
您可以在不使用linq的情况下在一次过程中解决它,如下所示:
bool isUpdated = false;
bool isImportant = false;
foreach (var state in item.States)
{
if (state == State.Important)
isImportant = true;
else if (state == State.Updated)
isUpdated = true;
if (isImportant && isUpdated)
break;
}
if (isImportant && isUpdated)
{
// ...
}
这不太可能成为一个问题,除非您有非常大的列表,而这些列表通常没有设置任何一个目标状态,因此您可能最好还是使用El Ronnoco的解决方案
如果有很多状态需要处理,可以通过编写如下扩展方法来简化:
public static class EnumerableExt
{
public static bool AllPredicatesTrueOverall<T>(this IEnumerable<T> self, params Predicate<T>[] predicates)
{
bool[] results = new bool[predicates.Length];
foreach (var item in self)
{
for (int i = 0; i < predicates.Length; ++i)
if (predicates[i](item))
results[i] = true;
if (results.All(state => state))
return true;
}
return false;
}
下面是一些使用它的示例代码:
enum State
{
Unknown,
Important,
Updated,
Deleted,
Other
}
void run()
{
IEnumerable<State> test1 = new[]
{
State.Important,
State.Updated,
State.Other,
State.Unknown
};
if (test1.AllPredicatesTrueOverall(s => s == State.Important, s => s == State.Updated))
Console.WriteLine("test1 passes.");
else
Console.WriteLine("test1 fails.");
IEnumerable<State> test2 = new[]
{
State.Important,
State.Other,
State.Other,
State.Unknown
};
if (test2.AllPredicatesTrueOverall(s => s == State.Important, s => s == State.Updated))
Console.WriteLine("test2 passes.");
else
Console.WriteLine("test2 fails.");
// And to show how you can use any number of predicates:
bool result = test1.AllPredicatesTrueOverall
(
state => state == State.Important,
state => state == State.Updated,
state => state == State.Other,
state => state == State.Deleted
);
}
您可以轻松指定更多状态:
if (item.States.AllStatesSet(State.Important, State.Updated, State.Deleted))
如果必须使用Linq:
if (item.States.Any(state => state == State.Important) && item.States.Any(state => state == State.Updated))
否则,只需使用@ElRonnoco所说的内容
然而,如果你的州是2的幂,那么这个答案将略有不同
这种方法的问题在于,如果两种状态都没有设置,它会在集合上完全迭代两次。如果这种情况经常发生,它将比可能的要慢
您可以在不使用linq的情况下在一次过程中解决它,如下所示:
bool isUpdated = false;
bool isImportant = false;
foreach (var state in item.States)
{
if (state == State.Important)
isImportant = true;
else if (state == State.Updated)
isUpdated = true;
if (isImportant && isUpdated)
break;
}
if (isImportant && isUpdated)
{
// ...
}
这不太可能成为一个问题,除非您有非常大的列表,而这些列表通常没有设置任何一个目标状态,因此您可能最好还是使用El Ronnoco的解决方案
如果有很多状态需要处理,可以通过编写如下扩展方法来简化:
public static class EnumerableExt
{
public static bool AllPredicatesTrueOverall<T>(this IEnumerable<T> self, params Predicate<T>[] predicates)
{
bool[] results = new bool[predicates.Length];
foreach (var item in self)
{
for (int i = 0; i < predicates.Length; ++i)
if (predicates[i](item))
results[i] = true;
if (results.All(state => state))
return true;
}
return false;
}
下面是一些使用它的示例代码:
enum State
{
Unknown,
Important,
Updated,
Deleted,
Other
}
void run()
{
IEnumerable<State> test1 = new[]
{
State.Important,
State.Updated,
State.Other,
State.Unknown
};
if (test1.AllPredicatesTrueOverall(s => s == State.Important, s => s == State.Updated))
Console.WriteLine("test1 passes.");
else
Console.WriteLine("test1 fails.");
IEnumerable<State> test2 = new[]
{
State.Important,
State.Other,
State.Other,
State.Unknown
};
if (test2.AllPredicatesTrueOverall(s => s == State.Important, s => s == State.Updated))
Console.WriteLine("test2 passes.");
else
Console.WriteLine("test2 fails.");
// And to show how you can use any number of predicates:
bool result = test1.AllPredicatesTrueOverall
(
state => state == State.Important,
state => state == State.Updated,
state => state == State.Other,
state => state == State.Deleted
);
}
您可以轻松指定更多状态:
if (item.States.AllStatesSet(State.Important, State.Updated, State.Deleted))
列表有一个Contains方法,所以您的代码
if(item.States.Contains(State.Important) && item.States.Contains(State.Updated))
string toProcess = "Do";
我看不出在这里使用Linq或lambda表达式有什么真正的好处…列表有一个Contains方法,所以您的代码应该是
if(item.States.Contains(State.Important) && item.States.Contains(State.Updated))
string toProcess = "Do";
我认为在这里使用Linq或lambda表达式没有什么真正的好处…您可以选择
!(new List<States>{State.Important, State.Updated}.Except(item.States).Any());
它不是很短,但是如果你有大量的州要检查,它会更容易
只要您想检查项目是否具有所需的所有状态,您只需将新状态添加到第一个列表中。您可以使用
!(new List<States>{State.Important, State.Updated}.Except(item.States).Any());
它不是很短,但是如果你有大量的州要检查,它会更容易
只要您想检查该项是否具有所需的所有状态,您只需将新状态添加到第一个列表中。以下某种实现
Content obj = new Content();
obj.States = SomeMethod();
if(obj.States.Any(h => h == State.Important) && obj.States.Any(h => h == State.Updated))
{
string toProcess = "Do";
}
某种形式的后续实现
Content obj = new Content();
obj.States = SomeMethod();
if(obj.States.Any(h => h == State.Important) && obj.States.Any(h => h == State.Updated))
{
string toProcess = "Do";
}
试试这个
试试这个
也许你可以考虑使用你的枚举作为一组标志,也就是说你可以组合多个状态而没有列表:[Flags]
public enum State
{
Important = 1,
Updated = 2,
Deleted = 4,
XXX = 8
....
}
public class Content
{
public State MyState { get; set; }
}
if ((myContent.MyState & State.Important) == State.Important
&& (myContent.MyState & State.Updated) == State.Updated)
{
// Important AND updated
}
也许你可以考虑使用EnUM作为一组标志,也就是说,你可以组合多个状态而没有列表:
[Flags]
public enum State
{
Important = 1,
Updated = 2,
Deleted = 4,
XXX = 8
....
}
public class Content
{
public State MyState { get; set; }
}
if ((myContent.MyState & State.Important) == State.Important
&& (myContent.MyState & State.Updated) == State.Updated)
{
// Important AND updated
}
+提到旗帜——这听起来可能是一个很好的方法。与其有一个状态列表,不如有一个状态变量本身可以作为列表…@PaoloTedesco道歉-我误解了原来的问题。然而,我认为我的阅读最终是正确的!用这种方式编写15+个状态的组合听起来不是一个好方法。我有很多基于状态组合的if条件。有些甚至是动态的,作为另一个列表出现,这就是为什么寻找Linq或Lambda@Nirav我添加了更多的例子。+1用于提及旗帜-这听起来可能是一个很好的OP方法。与其有一个状态列表,不如有一个状态变量本身可以作为列表…@PaoloTedesco道歉-我误解了原来的问题。然而,我认为我的阅读最终是正确的!用这种方式编写15+个状态的组合听起来不是一个好方法。我有很多基于状态组合的if条件。有些甚至是动态的,作为另一个列表出现,这就是为什么寻找Linq或Lambda@Nirav我添加了更多的例子。我不知道这件事是否是故意的,但请不要改变它:是的,我担心这是故意的。我不能只是不小心把那种喜剧的金块扔了!!我不知道这件事是否是故意的,但请不要改变它:是的,恐怕是故意的。我不能只是不小心把那种喜剧的金块扔了!!这只是If条件的一个例子。我知道。但以Has为例。我有很多基于状态组合的if条件。有些甚至是动态的,作为另一个列表出现,这就是为什么寻找Linq或LambdaI没有看到这有什么问题。只需为每个条件创建一个状态列表,并在此应用任何答案即可。你可以扩展我的答案,例如,轻松处理许多案例。这只是If条件的一个例子。我知道。但以Has为例。我有
许多if条件基于状态的组合。有些甚至是动态的,作为另一个列表出现,这就是为什么寻找Linq或LambdaI没有看到这有什么问题。只需为每个条件创建一个状态列表,并在此应用任何答案即可。你可以扩展我的回答,例如,轻松处理许多案件。