Lamda表达式VS FirstOrDefault

时间:2018-11-09 13:38:24

标签: c# lambda

我是使用lamda expressions的新手,并且正在尝试弄清楚一些事情。 我创建了以下代码部分,该代码返回日志文件的文件路径。

public static string GetLogFile()
{
    var fileTarget = LogManager.Configuration.AllTargets.Where(t=>t.Name == "LogName") as FileTarget;            
    return fileTarget == null ? string.Empty : fileTarget.FileName.Render(new LogEventInfo { Level = LogLevel.Info });
}

我的问题是,fileTarget在我使用时为空:

LogManager.Configuration.AllTargets.Where(t=>t.Name == "LogName")

但是如果我将代码行更改为

LogManager.Configuration.AllTargets.FirstOrDefault(t=>t.Name == "LogName")

返回我的日志文件的正确路径。有人可以向我解释WhereFirstOrDefault之间是否有主要区别吗?

3 个答案:

答案 0 :(得分:2)

在您的情况下,Where返回对象IEnumerable的{​​{1}}(简称为列表)。然后,将此列表转换为FileTarget。这就是为什么它为空。

但是FileTarget返回一个对象或FirstOrDefault,并且可以强制转换为您的类null。这就是为什么它起作用。

答案 1 :(得分:2)

实际返回IEnumerable的地方(智能会告诉您这一点)。它不知道您的谓词可能匹配多少个项目。 FirstOrDefault将获取第一项或与谓词匹配的第一项。如果您通过了。

(Nb。谓词是接受对象并返回布尔值的任何函数,有一个称为Predicate<T>的.Net类型代表它)

使用OfType linq运算符以及null传播和null合并运算符

public static string GetLogFile()
{
    var fileTarget = LogManager.Configuration.AllTargets.OfType<FileTarget>().FirstOrDefault(t=>t.Name == "LogName");            
    return fileTarget?.FileName.Render(new LogEventInfo { Level = LogLevel.Info }) ?? string.Empty;
}

答案 2 :(得分:1)

简单地说,

Where将为您提供枚举。不会为null。如果谓词中没有匹配项,则为空。 FirstOrDefault将为您提供一个对象。如果没有匹配项,则为null。

按照您的代码进行操作,它将引发编译错误,表明它无法从IEnumerable转换为FileTarget。