FirstOrDefault()结果集合的结果?

时间:2013-03-14 10:46:39

标签: linq c#-4.0 struct

所以我收到了struct的集合(它实际上是一个WCF数据合同,但我认为这与此无关)。

List<OptionalExtra> OptionalExtras;

OptionalExtrastruct

public partial struct OptionalExtra

现在我正在运行以下声明:

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

}

现在这不会编译:

  

operator!=不能应用于OptionalExtra类型的opperands   和'<null>'

经过一番谷歌搜索后,我意识到这一点,因为OptionalExtrastruct。除非定义为可空类型,否则我认为不可为空?

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

这个应该永远不会发生,但比抱歉更安全。

7 个答案:

答案 0 :(得分:48)

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

如果您认为会有一个元素并且您的代码无法使用空集合,使用First()而不是,因为当您的集合为空时,这将引发异常。快速失败通常比返回错误数据更好。

如果你不能假设会有一个元素,但也不能处理struct default初始化,你可以使struct可以为空,例如如下:

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

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

TL; DR;

    如果序列为空,
  • .FirstOrDefault<T>()会返回default(T)
  • 如果您认为列表非空,请使用.First()
  • 转换为可为空,然后在您不能认为列表为非空时使用.FirstOrDefault<T>()

答案 1 :(得分:6)

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

default( OptionalExtra )

如果要返回null,可以将列表转换为OptionalExtra?

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

然后,您可以测试null

答案 2 :(得分:3)

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

对于参考类型,默认值为null

答案 3 :(得分: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);

答案 4 :(得分:2)

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

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

答案 5 :(得分:0)

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

private void playSong() {
    try {
        mp.reset();
        mp.setDataSource(context, Uri.parse(url));
        mp.setAudioStreamType(AudioManager.STREAM_MUSIC);

        mp.prepareAsync();
    //  Log.d("*** AUDIO DURATION ***", mp.getDuration() + "  " + "  ");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

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

答案 6 :(得分:-1)

假设Code是一个字符串,用于我的答案,你应该只能测试该值的默认值。

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

}