Подтвердить что ты не робот

FirstOrDefault() результат сборки структуры?

Итак, у меня есть коллекция struct (это фактически WCF datacontract, но я предполагаю, что это не имеет никакого отношения здесь).

List<OptionalExtra> OptionalExtras;

OptionalExtra является struct.

public partial struct OptionalExtra

Теперь я запускаю следующую инструкцию:

OptionalExtra multiOptExtra = OptionalExtras.Where(w => w.Code == optExtra.Code).FirstOrDefault();
if (multiOptExtra != null)
{

}

Теперь это не скомпилируется:

оператор!= не применим к opperands типа OptionalExtra и '<null>'

После небольшого поиска я понял это, потому что OptionalExtra - struct. Который, я считаю, не может быть нулевым, если он не определен как нулевой тип?

Итак, мой вопрос: если мой оператор where не возвращает результатов, каков будет результат вызова FirstOrDefault? Вызывает ли это исключение?

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

4b9b3361

Ответ 1

Если ваша коллекция пуста, FirstOrDefault вернет default(OptionalExtras). Значение по умолчанию для struct - это структура со всеми ее значениями, которые по умолчанию инициализируются по умолчанию (то есть нуль, нуль и т.д.).

Если вы предположите, что будет элемент, а ваш код не будет работать с пустой коллекцией, Использовать First() вместо, так как это вызовет исключение, когда ваша коллекция пуста. Как правило, лучше отказываться быстрее, чем возвращать неверные данные.

Если вы не можете предположить, что будет элемент, но также не может иметь дело с инициализацией по умолчанию для структуры, вы можете сделать структуру обнуляемой, например, следующим образом:

OptionalExtras
    .Where(w => w.Code == optExtra.Code)
    .Cast<OptionalExtras?>()
    .FirstOrDefault();

Таким образом вы можете получить нулевой возврат даже для структуры. Основная идея здесь заключается в том, чтобы расширить набор возможных значений, включив что-то, отличное от OptionalExtras, чтобы разрешить обнаружение пустого списка. Если вам не нравятся нулевые значения, вместо этого вы можете использовать реализацию Maybe<> (не встроенную .NET) или использовать пустые или одиночные списки (например, .Take(1).ToArray(). Однако, с помощью nullable struct, скорее всего, ваш лучший выбор.

TL; DR;

  • .FirstOrDefault<T>() возвращает default(T), если последовательность пуста
  • Используйте .First(), если вы предполагаете, что список не пуст.
  • Присвоить значение null, а затем использовать .FirstOrDefault<T>(), если вы не можете предположить, что список не пуст.

Ответ 2

Как говорили другие, результат вашего кода, когда никакие элементы не совпадают, будет:

default( OptionalExtra )

Если вы хотите вернуть null, вы можете сделать свой список OptionalExtra?

OptionalExtra? multiOptExtra = OptionalExtras.Cast<OptionalExtra?>().Where( ...

Затем вы можете проверить null

Ответ 3

Результатом будет значение по умолчанию вашей структуры, например. default(OptionalExtras).

В то время как для ссылочного типа значение по умолчанию null.

Ответ 4

он предоставляет вам значение defualt для вашей структуры, как показано ниже

int[] numbers = { };
int first = numbers.FirstOrDefault();
Console.WriteLine(first);//this print 0 as output 

Другая опция для обработки - использовать значение по умолчанию, как показано ниже

List<int> months = new List<int> { };
// Setting the default value to 1 by using DefaultIfEmpty() in the query. 
int firstMonth2 = months.DefaultIfEmpty(1).First();
Console.WriteLine("The value of the firstMonth2 variable is {0}", firstMonth2);

Ответ 5

Если default(OptionExtra) по-прежнему является допустимым значением, лучше изменить код на этот

var results = OptionalExtras.Where(w => w.Code == optExtra.Code).Take(1).ToList();
if (results.Any()) {
   multiOptExtra = results[0]
}

Ответ 6

Предполагая, что код является строкой для моего ответа, вы должны просто проверить это значение по умолчанию.

OptionalExtra multiOptExtra = OptionalExtras.Where(w => w.Code == optExtra.Code).FirstOrDefault();
if (multiOptExtra.Code != null)
{

}

Ответ 7

Если вы хотите проверить значение null, используйте System.Nullable collection:

var OptionalExtras = new List<OptionalExtra?>();
/* Add some values */
var extras = OptionalExtras.FirstOrDefault(oe => oe.Value.Code == "code");
if (extras != null)
{
    Console.WriteLine(extras.Value.Code);
}

Обратите внимание, что для доступа к элементу необходимо использовать значение.