22

I have class with multiple properties;

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

}

sometimes this object return me with value in any property say

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

remaining values are null. This is OK

But, How do I check when all values in properties of objects are null

like string.IsNullOrEmpty() for object ?

curretly I am checking like this;

if(emp.FIRST_NAME == null && emp.LAST_NAME == null && emp.TYPE == null && emp.departmentList == null ...)
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
Abdul
  • 1,416
  • 9
  • 26
  • 57
  • 13
    Your object has 6 properties - one of them is not even nullable - which makes 5. You're better off just checking each for null than some complex reflection-based scenario. The way you're doing it is arguably the *right* way. – Jamiec May 02 '18 at 07:02
  • 2
    What about creating a function in your class that does this for you? So you call it whenever you need it. – git_gud May 02 '18 at 07:03
  • 1
    Your current check is both relaiable and readable. You may want to split it up over multiple lines (one check per line) even if it is only huge condition. Also a few versions ago they added null-conditional operators to C#6. Those might be a better option for single line checks. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators – Christopher May 02 '18 at 07:04
  • `like string.IsNullOrEmpty() for object ?` Just to clarify what _could be_ a misunderstanding here: an object that is `null` is not the same as an object whose properties are all `null`. If you don't distinguish between the two, you're going to face a lot of misunderstandings whenever you talk about your code. – Flater May 02 '18 at 14:42
  • @Flater there is lot misunderstanding about that, could you suggest any good readings – Abdul May 03 '18 at 04:30

2 Answers2

28

EDIT

This answer has received some votes in the last time, so I decided to improve it a little, adding simple caching so that ArePropertiesNotNull does not retrieve the properties every time it is called, but rather only once for every type.

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

(Old answer below.)


You could use reflection as proposed by Joel Harkes, e.g. I put together this reusable, ready-to-use extension method

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

which can then be called like this

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

And now you can check the areAllPropertiesNotNull flag which indicates whether all properties are not null. Returns true if all properties are not null, otherwise false.


Advantages of this approach

  • It doesn't matter whether or not the property type is nullable or not for the check.
  • Since above method is generic, you can use it for any type you want and don't have to write boilerplate code for every type you want to check.
  • It is more future-proof in case you change the class later. (noted by ispiro).

Disadvantages

  • Reflection can be quite slow, and in this case it is certainly slower than writing explicit code as you currently do. Using simple caching (as proposed by Reginald Blue will remove much of that overhead.

In my opinion, the slight performance overhead can be neglected since development time and repetition of code are reduced when using the ArePropertiesNotNull, but YMMV.

Community
  • 1
  • 1
Thomas Flinkow
  • 4,845
  • 5
  • 29
  • 65
  • 2
    Reflection is also more future-proof in case you change the class and forget to change the testing method. – ispiro May 02 '18 at 11:48
  • 2
    so... what's typically slow about reflection is the part where you're trying to find all of the properties (or whatever). If this is something that's needed to be done a lot, caching the properties into an array will speed it up considerably. – Reginald Blue May 02 '18 at 12:19
  • @ThomasFlinkow Sure. – ispiro May 02 '18 at 12:28
  • 2
    `All(propertyInfo => propertyInfo.GetValue(obj) != null)` would only return true if **all** properties are **not** null. An object with all null properties would render the same result (false) as an object with only a single null property (false), which is not the point of the test as per OP's description. I assume you either mean `Any(propertyInfo => propertyInfo.GetValue(obj) != null)` or `! All(propertyInfo => propertyInfo.GetValue(obj) == null)` (notice the inversion on the second one) – Flater May 02 '18 at 14:45
  • @ThomasFlinkow please edit the answer from `.Any` to `.All` so I mark this as accepted, and I assume that `.GetValue()` needs two parameters, `.GetValue(obj, null)`. – Abdul May 03 '18 at 04:27
  • @trighati please see the edited answer. Also, while there exists the `PropertyInfo.GetValue(object, object)` overload, I chose to go with [`PropertyInfo.GetValue(object)`](https://msdn.microsoft.com/en-us/library/hh194385(v=vs.110).aspx) so that I don't have to pass `null`. Of course you can use either, its completely up to you and will make no difference whatsoever. Thank you for marking this as accepted. – Thomas Flinkow May 03 '18 at 05:42
9

Either you do this by writing down the code to check every property manually (best option) or you use reflection (read more 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;

example from here

Note that int cannot be null! and its default value will be 0. thus its better to check prop == default(int) than == null

option 3

Another option is to implement INotifyPropertyChanged.

On a change set a boolean field value isDirty to true and than you only need to check if this value is true to know if any property has been set (even if property was set with null.

Warning: this method every property can still be null but only checks if a setter was called (changing a value).

Community
  • 1
  • 1
Joel Harkes
  • 10,975
  • 3
  • 46
  • 65