C#优雅的方法来检查是否所有浅属性都为null(或者任何属性都不为null)

本文关键字:null 属性 或者 任何 方法 是否 检查 | 更新日期: 2023-09-27 18:25:13

当我读到这个问题时深度空检查,有更好的方法吗?

和这个

C#优雅的方法来检查属性是否';s属性为空

假设我想检查是否所有属性都不是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

(如果我们希望以上所有属性都不为空)

SearchCriteria
.Has(criteria => criteria.Keywork).Or()
.Has(criteria => criteria.SectorId).Or()
.Has(criteria => criteria.HasOption).Or()
.etc

(如果我们希望任何属性不为空)

SearchCriteria
.Has(criteria => criteria.Keywork).Or()
.Has(criteria => criteria.SectorId)
.Has(criteria => criteria.HasOption)
.etc

(如果我们希望关键字SectorId具有值HasOption具有值。

那么,我们在codeplex上有任何现有的项目吗?或者任何可以将深度空检查和浅空检查结合起来的优雅方法

C#优雅的方法来检查是否所有浅属性都为null(或者任何属性都不为null)

坦率地说,我会坚持使用涉及||&&== null!= null的简单版本。它直接有效,并允许立即短路。如果你要做lots,你可能会写一个实用程序类,它使用元编程(可能是ExpressionILGenerator)为每个类型创建一个优化的方法,检查所有属性,然后:

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();
            }
        }
    }
}

虽然我确实支持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(...