在LINQ中返回null而不是默认值

19

我有一个 LINQ 查询需要检索一些 DateTime 值。有时候我没有匹配项,必须返回 NULL 来代替 DateTime 的默认值。

我如何避免返回 DateTime 的默认值并返回 NULL?

我的 LINQ:

CreatedDate = ctaMatch.Select(d => d.CreatedDate).DefaultIfEmpty().FirstOrDefault()

在 DefaultIfEmpty 中,我只能放置 DateTime。


2
你不能有一个空的DateTime,因为它是一个值类型。你可以使用可空类型(DateTime?)。 - Mephy
3个回答

30
将其转换为DateTime?,这将导致如果集合为空,则 DefaultIfEmpty 创建一个包含null值的默认集合。
CreatedDate = ctaMatch
    .Select(d => (DateTime?)d.CreatedDate)
    .DefaultIfEmpty()
    .FirstOrDefault()

备注: 可以省略 DefaultIfEmpty,因为其后面跟着 FirstOrDefault


1
通过使用 DefaultIfEmpty(),这不会使 FirstOrDefault() 中的 Default 失去意义吗?这应该改为 First() 吗? - StoriKnow
@Sam,如果后面跟着 FirstOrDefault,那么它就不是必需的。 - Yuliam Chandra
使用可空 DateTime 进行转换的技巧非常酷。这将更改 FirstOrDefault 的行为,使其在处理标量时返回 null 而不是默认值。 - Mariusz

14
你可以使用对象的空值条件运算符 ?. 来操作包含日期属性的对象:空值条件运算符
DateTime? date = ctaMatch.FirstOrDefault()?.CreatedDate;
如果你的集合中 FirstOrDefault() 返回了 null,那么空值条件运算符将返回 null 作为 CreatedDate 属性的值。
或者,您可以选择日期并将其显式转换为 Nullable<DateTime>
DateTime? date = ctaMatch.Select(d => (DateTime?)d.CreatedDate).FirstOrDefault();

...从而为其赋予了默认值null


我猜你可以编写一个通用的扩展方法,public static TValue? FirstOrNull<TValue>(this IEnumerable<TValue> source) where TValue : struct { return source.Select(x => (TValue?)x).FirstOrDefault(); } - Jeppe Stig Nielsen

3

替代语法... 如果存在Any,则获取First元素;否则使用null

DateTime? CreatedDate = ctaMatch.Any() ? ctaMatch.First().CreatedDate : (DateTime?)null;

最后的转换是否必要? (DateTime?)。如果 CreatedDate 是 DateTime? 类型,则仅分配 null 即可完成任务。CreatedDate = ctaMatch.Any() ? ctaMatch.First() : null; - broadband
1
如果CreatedDate已经是DateTime?类型,那么你是对的——强制转换是不必要的。但在OP的情况下,CreatedDate是一个非空的DateTime,因此默认值是"1/1/0001",而他不想要这个值。在这种情况下,强制转换是必要的。 - Grant Winney
我想你的意思是非空的 DateTime 只是 DateTime createdDate(没有在 DateTime 结尾加上 ?)。即使 CreatedDate 是非空的,你也不能使用 DateTime 强制转换进行赋值。DateTime CreatedDate = (DateTime?)null; 无法编译。 - broadband

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接