So say I have a class Student with one property, int Age
. Now if I have List<Student> students
, how do I check if the age of all students in the list is equal?

- 1,853
- 6
- 28
- 44
-
1See http://stackoverflow.com/questions/5478681/using-linq-can-i-verify-a-property-has-the-same-value-for-all-objects – goodeye Oct 06 '14 at 16:50
6 Answers
You can check by using All
method, presumably your list have students:
var firstStudent = students.First();
students.All(s => s.Age == firstStudent.Age);

- 74,024
- 28
- 151
- 206
-
3It would probably be better to hoist the `First` out first, though – Marc Gravell Aug 28 '13 at 11:28
-
Your first implementation wasn't that bad because enumerating until the first element is not expensive. – Alex Siepman Aug 28 '13 at 11:30
-
@AlexSiepman that depends totally on what `students` is... it *could* be. – Marc Gravell Aug 28 '13 at 11:32
-
I'd normally try to avoid querying a sequence twice when you can do the same in one call... – Rawling Aug 28 '13 at 11:34
-
If finding the first non-matching element is (potentially) faster you can use `!students.Any(s => s.Age != firstStudent.Age)` – Sam Aug 28 '13 at 11:39
-
1
-
1@CuongLe Yep, seems like they both short circuit ([Any vs All](http://stackoverflow.com/questions/9027530/linq-not-any-vs-all-dont)) and All is easier to read (in this case) – Sam Aug 28 '13 at 12:00
If you want to do this in one query, not two (which is generally bad practice),
bool allAgesAreTheSame = (students.Select(s => s.Age).Distinct().Count() < 2);
will do it for you.
This will also return true in the trivial case where you have no students at all, rather than throw an exception. (You could do == 1
rather than < 2
to return false in the trivial case instead.)

- 49,248
- 7
- 89
- 127
-
1An intersting thought: you could add a `Take(2)` between the `Distinct()` and the `Count()`, which would allow for a level of short-circuiting - however, it would have the overhead of an extra iterator - so whether this is a good thing depends on whether a large number of different ages would be a likely scenario – Marc Gravell Aug 28 '13 at 11:40
-
@Marc Good point, I'm quite disappointed in myself at using a `Count` when I really only want a "`0, 1 or 2`", usually I'm pretty good at spotting that stuff. – Rawling Aug 28 '13 at 11:44
-
1
-
1@Alex Yup, Marc has already pointed this out, and a solution, and a caveat to why you might not want to use the solution, for which reason I've left the solution in his comment rather than copy it into my answer. I'd still take this over a two-query solution. – Rawling Aug 28 '13 at 11:54
Just a random answer - not sure I'd do it this way in reality, but this will be brutally efficient:
- will use typed iterators if duck-typing is available (unlike LINQ which won't) - and note that
List<T>
does offer duck-typed iterators - no double-iterations
- no failures etc for empty sequences
- no delegates, capture-contexts, etc
- etc
Code:
using(var iter = students.GetEnumerator()) // a List<T>.Enumerator struct
{
if(!iter.MoveNext()) return true; // or false, as you define for "empty"
int age = iter.Current.Age;
while(iter.MoveNext())
if(iter.Current.Age != age)
return false;
return true;
}

- 1,026,079
- 266
- 2,566
- 2,900
If students can have 0 elements you can do this:
var firstStudent = students.FirstOrDefault();
var areSame =students.All(s => s.Age == firstStudent.Age);

- 2,499
- 23
- 31
-
2@Rawling I tested the solution and it did **not** throw an exception because if there are 0 elements, the All() method will return true without trying to execute the lambda predicate! – Alex Siepman Aug 28 '13 at 13:20
If you can't use linq, you can always loop all the students:
private bool sameAge (List<Student> students)
{
int auxAge = students.Count > 0? students[0].Age : 0;
foreach (Student stu in students)
{
if (stu.Age != auxAge)
return false;
}
return true;
}

- 9,692
- 15
- 60
- 89
If you just have to check this once, the marked answere is best solution. To use it multiple times in your code just write a static extension to check equality of property:
public static bool GetIdenticProperty<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> predicate)
{
IEnumerable<TSource> enumerable = source as IList<TSource> ?? source.ToList();
if ((!enumerable.Any()) || (enumerable.Count() == 1))
return true; // or false if you prefere
var firstItem = enumerable.First();
bool allSame = enumerable.All(i => Equals(predicate(i), predicate(firstItem)));
return allSame;
}
If you want to use the value of the property later on lets return that value:
public static TKey GetIdenticProperty<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> predicate)
{
IEnumerable<TSource> enumerable = source as IList<TSource> ?? source.ToList();
if (!enumerable.Any())
return default(TKey);
var firstItem = enumerable.First();
bool allSame = enumerable.All(i => Equals(predicate(i), predicate(firstItem)));
return allSame ? predicate(firstItem) : default(TKey);
}
But using this code you have to check weather the returnd value is null
or default(TKey)
relating to the type of property.

- 41
- 5