Как проверить, является ли значение свойства для каждого члена списка одинаковым

Так сказать, у меня есть класс Student с одним свойством, int Age. Теперь, если у меня есть List<Student> students, как проверить, равен ли возраст всех учеников в списке?

Ответ 1

Вы можете проверить с помощью метода All, предположительно, у вашего списка есть ученики:

var firstStudent = students.First();
students.All(s => s.Age == firstStudent.Age);

Ответ 2

Если вы хотите сделать это в одном запросе, а не в двух (что обычно плохо),

bool allAgesAreTheSame = (students.Select(s => s.Age).Distinct().Count() < 2);

сделает это за вас.

Это также вернет true в тривиальном случае, когда у вас нет учеников вообще, вместо того, чтобы бросать исключение. (Вместо < 2 вы можете сделать == 1, чтобы вместо этого возвращать значение false в тривиальном случае.)

Ответ 3

Если у студентов может быть 0 элементов, вы можете сделать это:

var firstStudent = students.FirstOrDefault();
var areSame =students.All(s => s.Age == firstStudent.Age);

Ответ 4

Просто случайный ответ - не уверен, что я сделаю это так на самом деле, но это будет жестоко эффективным:

  • будет использовать типизированные итераторы, если доступна утиная печать (в отличие от LINQ, которая не будет) - и обратите внимание, что List<T> делает предлагать итераторы с утиным текстом
  • нет двойных итераций
  • нет ошибок и т.д. для пустых последовательностей
  • нет делегатов, контекстов захвата и т.д.
  • и т.д.

код:

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;
}

Ответ 5

Если вы не можете использовать linq, вы можете всегда зацикливать всех студентов:

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;
}

Ответ 6

Если вам просто нужно это проверить один раз, то наилучшим решением будет отмеченный ответ. Чтобы использовать его несколько раз в вашем коде, просто напишите статическое расширение, чтобы проверить равенство свойства:

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;
}

Если вы хотите использовать значение свойства позже, давайте вернем это значение:

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);
}

Но используя этот код, вы должны проверить погоду, значение returnd равно null или default(TKey), относящееся к типу свойства.