在单个LINQ表达式中嵌入null测试
本文关键字:null 测试 单个 LINQ 表达式 | 更新日期: 2023-09-27 18:11:07
让我们从一个简单的示例类开始:
public class Foo
{
public DateTime Date { get; set; }
public decimal Price { get; set; }
}
然后创建一个列表:
List<Foo> foos = new List<Foo>;
我想根据日期返回列表中一个项目的格式化价格或"N/a",因此,例如,我可以写:
Foo foo = foos.FirstOrDefault(f => f.Date == DateTime.Today);
string s = (foo != null) ? foo.Price.ToString("0.00") : "N/A";
我想把上面的两行像这样组合如下:
string s = foos.FirstOrDefault(f => f.Date == DateTime.Today).Price.ToString("0.00") ?? "N/A";
然而,这并没有达到我想要的,因为如果(f => f.Date == DateTime.Today)
不返回Foo,那么会抛出NullReferenceException
。
因此,LINQ是否可能只创建一条语句来返回格式化的价格或"N/A"?
如果您先过滤然后选择,您可以使用空合并操作符(??
),如下所示:
string price = foos.Where(f => f.Date == DateTime.Today)
.Select(f => f.Price.ToString())
.FirstOrDefault() ?? "N/A";
一种方法是在调用ToString
之前简单地检查FirstOrDefault
的结果是否为null:
var todayFoo = foos.FirstOrDefault(f => f.Date == DateTime.Today);
var s = todayFoo != null ? todayFoo.Price.ToString("0.00") : "N/A";
另一种方法是为合并操作符创建扩展方法,该方法也接受投影委托,如:
public static class ObjectExt
{
public static T2 Coalesce<T1, T2>(
this T1 obj, Func<T1, T2> projection, T2 defaultValue)
{
if (obj == null)
return defaultValue;
return projection(obj);
}
}
然后像这样调用它:
var s = foos
.FirstOrDefault(f => f.Date == DateTime.Today)
.Coalesce(t => t.Price.ToString("0.00"), "N/A");
string s = foos.Where(f => f.Date == DateTime.Today).Select(f => f.Price.ToString("0.00")).FirstOrDefault();