44

所以我有一个structs 的集合(它实际上是一个 WCF 数据合同,但我假设这在这里没有影响)。

List<OptionalExtra> OptionalExtras;

OptionalExtra是一个struct

public partial struct OptionalExtra

现在我正在运行以下语句:

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

}

现在这不会编译:

运算符 != 不能应用于 OptionalExtra 类型的操作数和'<null>'

经过一番谷歌搜索后,我意识到这是OptionalExtra因为struct. 除非定义为可空类型,否则我认为它不可为空?

所以我的问题是,如果我的where语句没有返回任何结果,那么FirstOrDefault调用的结果是什么?它会抛出异常吗?

顺便说一句,这永远不会发生,但安全总比后悔好。

4

7 回答 7

70

如果您的收藏为空,FirstOrDefault将返回default(OptionalExtras). 结构的默认值是其所有值依次默认初始化的结构(即零、空等)。

如果您假设会有一个元素并且您的代码不适用于空集合,请使用 Use First()instead,因为当您的集合为空时会引发异常。快速失败通常比返回错误数据要好。

如果你不能假设会有一个元素,也不能处理结构默认初始化,你可以将集合中的结构设置为可为空的值类型,例如如下:

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

这样,即使对于结构,您也可以获得 null 返回。这里的关键思想是扩展可能值的集合以包含除 an 之外的其他内容,OptionalExtra以允许检测空列表。如果您不喜欢可空值,则可以改用Maybe<>实现(不是 .NET 内置),或使用空列表或单例列表(例如.Take(1).ToArray(). 但是,可空结构可能是您最好的选择。

TL;博士;

  • .FirstOrDefault<T>()default(T)如果序列为空则返回
  • .First()如果您假设列表非空,请改用。
  • 转换为可为空,然后.FirstOrDefault<T>()在您不能假定列表非空时使用。
于 2013-03-14T10:49:05.093 回答
7

正如其他人所说,当没有元素匹配时,您的代码结果将是:

default( OptionalExtra )

如果你想返回一个空值,你可以将你的列表转换为OptionalExtra?

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

然后你可以测试null

于 2013-03-14T10:52:27.330 回答
4

如果default(OptionExtra)仍然是有效值,最好将您的代码更改为此

var results = OptionalExtras.Where(w => w.Code == optExtra.Code).Take(1).ToList();
if (results.Any()) {
   multiOptExtra = results[0]
}
于 2013-03-14T10:54:59.007 回答
3

结果将是您的结构的默认值,例如default(OptionalExtras).

而对于引用类型,默认值为null.

于 2013-03-14T10:49:14.127 回答
2

它为您的结构提供默认值,如下所示

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);
于 2013-03-14T10:52:59.513 回答
0

如果要检查 null,请使用 System.Nullable 集合:

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

请注意,您必须使用 Value 来访问该元素。

于 2015-08-28T06:53:35.817 回答
-1

假设出于我的回答目的 Code 是一个字符串,您应该能够测试该值的默认值。

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

}
于 2013-08-13T18:22:32.897 回答