I\'m searching for a simple and fast way to check if all my Listitems have the same value for a member.
foreach (Item item in MyList)
{
Item.MyMember = &
Iam doing like so:
Item item = MyList.FirstOrDefault(x=>x.MyMember != valueToMatch);
bool allMembersSame = item == null;
Your own solution is simple enough already, but if you wanted to abstract away the loop and write it more expressively, you could use Linq.
bool allSame = MyList.All(item => item.MyMember == someValue);
using System.Linq;
…
if (myList.Any()) // we need to distinguish between empty and non-empty lists
{
var value = myList.First().MyMember;
return myList.All(item => item.MyMember == value);
}
else
{
return true; // or false, if that is more appropriate for an empty list
}
Here is a generic one that works for all version of .NET beginning with 2.0:
public static bool AllSameByProperty<TItem, TProperty>(IEnumerable<TItem> items, Converter<TItem, TProperty> converter)
{
TProperty value = default(TProperty);
bool first = true;
foreach (TItem item in items)
{
if (first)
{
value = converter.Invoke(item);
first = false;
continue;
}
TProperty newValue = converter.Invoke(item);
if(value == null)
{
if(newValue != null)
{
return false;
}
continue;
}
if (!value.Equals(newValue))
{
return false;
}
}
return true;
}
Its usage in C# 2.0:
AllSameByProperty(list, delegate(MyType t) { return t.MyProperty; });
Its usage in C# 3.0:
AllSameByProperty(list, t => t.MyProperty);
EDIT: Okay, after the new requirement has
bool allSame = !MyList.Select(item => item.MyMember)
.Where(x => !string.IsNullOrEmpty(x))
.Distinct()
.Skip(1)
.Any();
That avoids you having to take a first step of finding one sample value to start with. (And it will still exit as soon as it finds the second value, of course.)
It also only iterates over the sequence once, which may be important if it's not really a repeatable sequence. Not a problem if it's a List<T>
of course.
EDIT: To allay concerns over Skip
, from the documentation:
If source contains fewer than count elements, an empty
IEnumerable<T>
is returned. If count is less than or equal to zero, all elements of source are yielded.
I think this is the shortest and most elegant solution:
bool allSame = list.GroupBy(item => item.TheProperty).Count == 1;