当我读到这篇文章时,会出现这种担忧 Deep Null checking, is there a better way?
和这个
C# elegant way to check if a property's property is null
假设我想检查所有属性是否为null,或者是否有任何属性为null。(浅层属性)
SearchCriteria对象:
Keyword (Searches Name and Description) != null ||
SectorId != null ||
IndustryId != null ||
HasOption != null ||
HasFutures != null ||
30 properties to go...
正如我们所看到的,语法在某种程度上难以阅读。我想要像
这样的东西SearchCriteria
.Has(criteria => criteria.Keywork)
.Has(criteria => criteria.SectorId)
.Has(criteria => criteria.HasOption)
.etc
(如果我们希望以上所有属性都为null)
OR
SearchCriteria
.Has(criteria => criteria.Keywork).Or()
.Has(criteria => criteria.SectorId).Or()
.Has(criteria => criteria.HasOption).Or()
.etc
(如果我们想要任何属性为非null)
OR
SearchCriteria
.Has(criteria => criteria.Keywork).Or()
.Has(criteria => criteria.SectorId)
.Has(criteria => criteria.HasOption)
.etc
(如果我们想要关键字或,SectorId的值且 HasOption有值。
那么我们在codeplex上有任何已存在的项目吗?或者任何优雅的方法,可以结合深度空检查和浅空检查?
答案 0 :(得分:7)
坦率地说,我坚持使用涉及||
或&&
,== null
或!= null
的简单版本。它直接有效,并允许立即短路。如果您要执行此批次,您可以编写一个使用元编程(Expression
或ILGenerator
可能)的实用程序类来创建一个优化方法-type检查所有属性,然后:
if(MyHelper.AllNull(obj)) ... // note this is probably actually generic
完整示例:
using System;
using System.Linq.Expressions;
using System.Reflection;
static class Program
{
static void Main()
{
bool x = MyHelper.AnyNull(new Foo { }); // true
bool y = MyHelper.AnyNull(new Foo { X = "" }); // false
}
}
class Foo
{
public string X { get; set; }
public int Y { get; set; }
}
static class MyHelper
{
public static bool AnyNull<T>(T obj)
{
return Cache<T>.AnyNull(obj);
}
static class Cache<T>
{
public static readonly Func<T, bool> AnyNull;
static Cache()
{
var props = typeof(T).GetProperties(
BindingFlags.Instance | BindingFlags.Public);
var param = Expression.Parameter(typeof(T), "obj");
Expression body = null;
foreach(var prop in props)
{
if (!prop.CanRead) continue;
if(prop.PropertyType.IsValueType)
{
Type underlyingType = Nullable.GetUnderlyingType(
prop.PropertyType);
if (underlyingType == null) continue; // cannot be null
// TODO: handle Nullable<T>
}
else
{
Expression check = Expression.Equal(
Expression.Property(param, prop),
Expression.Constant(null, prop.PropertyType));
body = body == null ? check : Expression.OrElse(body, check);
}
}
if (body == null) AnyNull = x => false; // or true?
else
{
AnyNull = Expression.Lambda<Func<T, bool>>(body, param).Compile();
}
}
}
}
答案 1 :(得分:2)
虽然我确实支持Marc Gravell完全写出来的答案,如果你坚持不重复!= null
,你不需要创建任何自定义方法。 LINQ方法已经可以做你想要的了,例如:
new[] { SearchCriteria }.SelectMany(criteria => new object[] {
criteria.Keywork,
criteria.SectorId,
criteria.HasOption,
...
}).Any(p => p != null)
还要涵盖SearchCriteria
本身可能为null
的情况,您可以使用
new[] { SearchCriteria }.Where(criteria => criteria != null).SelectMany(...