【问题标题】:Checking if Object has null in every property检查 Object 是否在每个属性中都有 null
【发布时间】:2018-05-02 07:00:42
【问题描述】:

我有多个属性的类;

public class Employee
{
    public string TYPE { get; set; }
    public int? SOURCE_ID { get; set; }
    public string FIRST_NAME { get; set; }        
    public string LAST_NAME { get; set; }

    public List<Department> departmentList { get; set; }
    public List<Address> addressList { get; set; }

}

有时这个对象会在任何属性中返回我的值

Employee emp = new Employee();
emp.FIRST_NAME= 'abc';

剩余值为空。没关系

但是,我如何检查对象属性中的所有值何时为空

喜欢string.IsNullOrEmpty() 对象?

目前我正在这样检查;

if(emp.FIRST_NAME == null && emp.LAST_NAME == null && emp.TYPE == null && emp.departmentList == null ...)

【问题讨论】:

  • 您的对象有 6 个属性 - 其中一个甚至不能为空 - 这使得 5 个。您最好只检查每个是否为空,而不是一些复杂的基于反射的场景。你这样做的方式可以说是正确的方式。
  • 在你的类中创建一个为你做这件事的函数怎么样?因此,您可以在需要时调用它。
  • 您当前的支票既可靠又可读。您可能希望将其拆分为多行(每行一个检查),即使它只是一个巨大的条件。同样在几个版本之前,他们在 C#6 中添加了空条件运算符。对于单行检查,这些可能是更好的选择。 docs.microsoft.com/en-us/dotnet/csharp/language-reference/…
  • like string.IsNullOrEmpty() for object ? 只是为了澄清这里可能是的误解:null 的对象与属性全部为null 的对象不同。如果你不区分这两者,每当你谈论你的代码时,你就会面临很多误解。
  • @Flater 对此有很多误解,你能推荐任何好的阅读材料

标签: c# null


【解决方案1】:

编辑

这个答案在上次获得了一些投票,所以我决定对其进行一些改进,添加简单的缓存,以便ArePropertiesNotNull 不会在每次调用时都检索属性,而是每种类型只检索一次。

public static class PropertyCache<T>
{
    private static readonly Lazy<IReadOnlyCollection<PropertyInfo>> publicPropertiesLazy
        = new Lazy<IReadOnlyCollection<PropertyInfo>>(() => typeof(T).GetProperties());

    public static IReadOnlyCollection<PropertyInfo> PublicProperties => PropertyCache<T>.publicPropertiesLazy.Value;
}

public static class Extensions
{
    public static bool ArePropertiesNotNull<T>(this T obj)
    {
        return PropertyCache<T>.PublicProperties.All(propertyInfo => propertyInfo.GetValue(obj) != null);
    }
}

(下面的旧答案。)


您可以按照Joel Harkes 的建议使用反射,例如我整理了这个可重用、即用型的扩展方法

public static bool ArePropertiesNotNull<T>(this T obj)
{
    return typeof(T).GetProperties().All(propertyInfo => propertyInfo.GetValue(obj) != null);    
}

然后可以这样调用

var employee = new Employee();
bool areAllPropertiesNotNull = employee.ArePropertiesNotNull();

现在您可以检查areAllPropertiesNotNull 标志,它指示是否所有属性都不为空。如果所有属性都不为空,则返回true,否则返回false


这种方法的优点

  • 属性类型对于检查是否可以为空都没有关系。
  • 由于上述方法是通用的,您可以将它用于您想要的任何类型,而不必为您想要检查的每种类型编写样板代码。
  • 如果您以后更改课程,它更具前瞻性。 (ispiro 注明)。

缺点

  • 反射可能会很慢,在这种情况下,它肯定比您当前编写显式代码要慢。使用简单的缓存(Reginald Blue 提出的建议将消除大部分开销。

在我看来,轻微的性能开销可以忽略不计,因为使用ArePropertiesNotNull 时减少了开发时间和代码重复,但使用 YMMV。

【讨论】:

  • 反射也更具前瞻性,以防您更改类并忘记更改测试方法。
  • 所以......反射通常很慢的部分是您试图找到所有属性(或其他)的部分。如果这是需要做很多的事情,将属性缓存到数组中会大大加快速度。
  • @ThomasFlinkow 当然。
  • All(propertyInfo =&gt; propertyInfo.GetValue(obj) != null) 只会在 所有 属性 not 为空时返回 true。具有所有空属性的对象将呈现与仅具有单个空属性 (false) 的对象相同的结果 (false),根据 OP 的描述,这不是测试的重点。我假设您的意思是Any(propertyInfo =&gt; propertyInfo.GetValue(obj) != null)! All(propertyInfo =&gt; propertyInfo.GetValue(obj) == null)(注意第二个的倒置)
  • @ThomasFlinkow 请编辑从.Any.All 的答案,所以我将其标记为已接受,并且我假设.GetValue() 需要两个参数.GetValue(obj, null)
【解决方案2】:

您可以通过写下代码来手动检查每个属性(最佳选择)或使用反射(阅读更多 here

Employee emp = new Employee();
var props = emp.GetType().GetProperties())
foreach(var prop in props) 
{
   if(prop.GetValue(foo, null) != null) return false;
}
return true;

来自here的示例

注意 int 不能为空!其默认值为 0。因此检查prop == default(int) 比检查== null 更好

选项 3

另一种选择是实现INotifyPropertyChanged

在更改时将布尔字段值 isDirty 设置为 true,然后您只需检查此值是否为 true 即可知道是否设置了任何属性(即使属性设置为 null。

警告:此方法的每个属性仍然可以为 null,但仅检查是否调用了 setter(更改值)。

【讨论】:

  • 他们有int?,而不是int
  • @trighati 好吧,但你仍然可能忘记让所有属性都可以为空。
  • @JoelHarkes 如?
  • @trighati int 十进制数组浮点结构等
猜你喜欢
  • 2016-01-20
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 2015-01-13
相关资源
最近更新 更多