Linq を使用する必要がある場合、これは機能するはずです。
if (item.States.Any(state => state == State.Important) && item.States.Any(state => state == State.Updated))
それ以外の場合はContains()
、@ElRonnoco のように使用してください。
(ただし、州がフラグ (2 の累乗) の場合、この答えは少し異なります。)
このアプローチの問題点は、どちらの状態も設定されていない場合、コレクションを完全に 2 回反復処理することです。これが頻繁に発生する場合は、実際よりも遅くなります。
次のように、1回のパスで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;
}
この名前を考えるのに少し苦労しました。true
各述語について、述語が真であるシーケンス内に少なくとも 1 つの項目がある場合に返されます。しかし、それはメソッド名としては少し長いです... ;)
次に、あなたの例は次のようになります。
if (item.States.AllPredicatesTrueOverall(s => s == State.Important, s => s == State.Updated))
これを使用するサンプルコードを次に示します。
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
);
}
しかし、おそらく最も簡単なのは、拡張メソッドを作成することですIEnumerable<State>
(心配する状態列挙が 1 つしかない場合)。
public static class EnumerableStateExt
{
public static bool AllStatesSet(this IEnumerable<State> self, params State[] states)
{
bool[] results = new bool[states.Length];
foreach (var item in self)
{
for (int i = 0; i < states.Length; ++i)
if (item == states[i])
results[i] = true;
if (results.All(state => state))
return true;
}
return false;
}
}
その後、元のコードは次のようになります。
if (item.States.AllStatesSet(State.Important, State.Updated))
より多くの状態を簡単に指定できます。
if (item.States.AllStatesSet(State.Important, State.Updated, State.Deleted))