我有这个方法
private IList<Order> FilterOrders(string filterText)
{
string filterTextLowerCase = filterText.ToLower();
var filtered = _orders.Where(order =>
order.OrderIdFullOrderNumber.ToLower().Contains(filterTextLowerCase) ||
order.Name.ToLower().Contains(filterTextLowerCase) ||
order.Status.ToLower().Contains(filterTextLowerCase) ||
order.TimeRemaining.ToLower().Contains(filterTextLowerCase) ||
order.Address.ToLower().Contains(filterTextLowerCase) ||
order.City.ToLower().Contains(filterTextLowerCase) ||
order.State.Abbrev.ToLower().Contains(filterTextLowerCase) ||
order.PostalCode.ToLower().Contains(filterTextLowerCase)).ToList();
return filtered;
}
正如您所看到的,属性中可能存在nullreference异常,在Where Where表达式中检查null的最佳方法是什么?
答案 0 :(得分:9)
如果您使用的是C#6,则可以在访问对象属性或方法之前添加?.
空检查运算符:order?.State?.ToLower()....
有关新的null检查运算符的详细信息,请参阅this。
如果您使用较低版本,则必须为每个where子句添加额外的空检查:.Where(order => (order.State != null && order.State.ToLower()....)
答案 1 :(得分:4)
不确定这是漂亮还是丑陋。它确实为每个订单创建了一个临时数组,但它避免了大量的重复。
mypassword{HASHSTRING}
答案 2 :(得分:4)
添加此扩展方法:
public static string NullSafeToLower(this string s)
{
if (s == null)
{
s = string.Empty;
}
return s.ToLower();
}
然后通过调用“NullSafeToLower”替换对“ToLower”的调用。
答案 3 :(得分:3)
即使这个问题已经得到解答,另一种选择就是:
var myVar = orders.Where(o => (o.SomeProperty ?? "").ToLower() == "someValue");
虽然这不是很漂亮,但如果你只需要一次或两次,这可能不像扩展方法那么“重”,但如果你需要这么做(如你的例子)那么列为答案的扩展方法之一将为您提供更好的服务。
作为参考,我必须这样做,因为我当时正在处理的构建环境还不支持C#6.0。如果你在一个缓慢采用的环境中工作,那么有一个后备技巧是很好的(它发生了!)。只是想把它扔出去。 :)
答案 4 :(得分:2)
不幸的是,此时我无法使用C#6.0功能。
我最终创建了一个扩展方法来过滤列表,与另一个扩展方法Contains进行比较,该方法接受@ robert-mckee建议的StringComparison参数,并从@ jeppe-stig-nielsen演示。
public static IList<Order> FilterOrders(this IList<Order> orders, string filterText)
{
var filtered = orders.Where(order =>
order.OrderIdFullOrderNumber.Contains(filterText, StringComparison.OrdinalIgnoreCase) ||
order.Name.Contains(filterText, StringComparison.OrdinalIgnoreCase) ||
order.Status.Contains(filterText, StringComparison.OrdinalIgnoreCase) ||
order.TimeRemaining.Contains(filterText, StringComparison.OrdinalIgnoreCase) ||
order.Address.Contains(filterText, StringComparison.OrdinalIgnoreCase) ||
order.City.Contains(filterText, StringComparison.OrdinalIgnoreCase) ||
order.State.Abbrev.Contains(filterText, StringComparison.OrdinalIgnoreCase) ||
order.PostalCode.Contains(filterText, StringComparison.OrdinalIgnoreCase)).ToList();
return filtered;
}
public static bool Contains(this string source, string value, StringComparison comparison)
{
if (string.IsNullOrWhiteSpace(source))
{
return false;
}
return source.IndexOf(value, comparison) >= 0;
}
答案 5 :(得分:1)
添加以下扩展方法。
public static class StringHelper
{
public static string SafeToLower(this string value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
return value.ToLower();
}
}
您的代码将成为以下内容。
private IList<Order> FilterOrders(string filterText)
{
string filterTextLowerCase = filterText.ToLower();
var filtered = _orders.Where(order =>
order.OrderIdFullOrderNumber.SafeToLower().Contains(filterTextLowerCase) ||
order.Name.SafeToLower().Contains(filterTextLowerCase) ||
order.Status.SafeToLower().Contains(filterTextLowerCase) ||
order.TimeRemaining.SafeToLower().Contains(filterTextLowerCase) ||
order.Address.SafeToLower().Contains(filterTextLowerCase) ||
order.City.SafeToLower().Contains(filterTextLowerCase) ||
order.State.Abbrev.SafeToLower().Contains(filterTextLowerCase) ||
order.PostalCode.SafeToLower().Contains(filterTextLowerCase)).ToList();
return filtered;
}