Проверка, есть ли у объекта null в каждом свойстве

У меня есть класс с несколькими свойствами;

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

остальные значения равны нулю. Хорошо

Но как мне проверить, когда все ценности в свойствах объектов имеет значение null

вроде string.IsNullOrEmpty() для объекта?

в настоящее время я проверяю вот так;

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

У вашего объекта 6 свойств - одно из них даже не допускает значения NULL - что составляет 5. Лучше просто проверить каждое на значение NULL, чем какой-либо сложный сценарий, основанный на отражении. То, как вы это делаете, возможно, является способом верно.

Jamiec 02.05.2018 09:02

А как насчет создания в вашем классе функции, которая сделает это за вас? Так что вы вызываете его, когда вам это нужно.

SOROMEED 02.05.2018 09:03

Ваш текущий чек является надежным и читаемым. Вы можете разделить его на несколько строк (по одной проверке на строку), даже если это всего лишь огромное условие. Также несколько версий назад они добавили в C# 6 условные операторы NULL. Это может быть лучшим вариантом для однострочных проверок. docs.microsoft.com/en-us/dotnet/csharp/language-reference/…

Christopher 02.05.2018 09:04
like string.IsNullOrEmpty() for object ? Просто, чтобы прояснить, что может быть здесь недоразумение: объект, который является null, не то же самое, что объект, все свойства которого являются null. Если вы не будете различать их, вы столкнетесь с множеством недоразумений, когда будете говорить о своем коде.
Flater 02.05.2018 16:42

@Flater есть много недоразумений по этому поводу, не могли бы вы предложить какие-нибудь хорошие чтения

trighati 03.05.2018 06:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
18
5
13 737
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Либо вы делаете это, записывая код для проверки каждого свойства вручную (лучший вариант), либо используете отражение (подробнее здесь)

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

пример из здесь

Обратите внимание, что int не может быть нулевым! и его значение по умолчанию будет 0. Таким образом, лучше проверить prop == default(int), чем == null.

вариант 3

Другой вариант - реализовать INotifyPropertyChanged.

При изменении установите для логического поля isDirty значение true, и вам нужно только проверить, истинно ли это значение, чтобы узнать, было ли установлено какое-либо свойство (даже если свойство было установлено с нулевым значением.

Предупреждение: в этом методе каждое свойство может иметь значение NULL, но проверяет только, был ли вызван установщик (изменение значения).

У них есть int?, а не int.

Nisarg 02.05.2018 09:04

@trighati хорошо, но все же вы можете забыть сделать все свойства обнуляемыми.

Joel Harkes 02.05.2018 09:06

@JoelHarkes, например?

trighati 03.05.2018 06:32

@trighati int десятичные массивы, структуры с плавающей запятой и т. д.

Joel Harkes 03.05.2018 06:49
Ответ принят как подходящий

РЕДАКТИРОВАТЬ

Этот ответ получил несколько голосов в последний раз, поэтому я решил его немного улучшить, добавив простое кеширование, чтобы 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);
    }
}

(Старый ответ ниже.)


Вы можете использовать отражение, предложенное Джоэл Харкес, например. Я собрал этот многоразовый, готовый к использованию метод расширения

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.


Преимущества такого подхода

  • Не имеет значения, допускает ли данный тип свойства значение NULL или нет для проверки.
  • Поскольку указанный выше метод является общим, вы можете использовать его для любого типа, который вам нужен, и вам не нужно писать шаблонный код для каждого типа, который вы хотите проверить.
  • Это больше подходит для будущего, если вы измените класс позже. (отмечено Испиро).

Недостатки

  • Отражение может быть довольно медленным, и в этом случае оно определенно медленнее, чем написание явного кода, как вы это делаете сейчас. Использование простого кэширования (как предлагает Реджинальд Блю, удалит большую часть этих накладных расходов.

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.

Отражение также более перспективно, если вы измените класс и забудете изменить метод тестирования.

ispiro 02.05.2018 13:48

Итак ... что обычно медленнее в отражении, так это в той части, где вы пытаетесь найти все свойства (или что-то еще). Если это что-то, что нужно сделать много, кеширование свойств в массив значительно ускорит его.

Reginald Blue 02.05.2018 14:19

@ThomasFlinkow Конечно.

ispiro 02.05.2018 14:28
All(propertyInfo => propertyInfo.GetValue(obj) != null) вернет истину только в том случае, если свойства все равны нулю нет. Объект со всеми нулевыми свойствами будет отображать тот же результат (false), что и объект только с одним нулевым свойством (false), что не является точкой теста в соответствии с описанием OP. Я предполагаю, что вы имеете в виду Any(propertyInfo => propertyInfo.GetValue(obj) != null) или ! All(propertyInfo => propertyInfo.GetValue(obj) == null) (обратите внимание на инверсию на втором)
Flater 02.05.2018 16:45

@ThomasFlinkow, пожалуйста, отредактируйте ответ с .Any на .All, чтобы я пометил его как принятый и предполагаю, что для .GetValue() нужны два параметра, .GetValue(obj, null).

trighati 03.05.2018 06:27

@trighati см. отредактированный ответ. Кроме того, хотя существует перегрузка PropertyInfo.GetValue(object, object), я решил использовать PropertyInfo.GetValue(object), чтобы мне не приходилось передавать null. Конечно, вы можете использовать и то, и другое, это полностью зависит от вас и не будет иметь никакого значения. Спасибо, что отметили это как принятый.

Thomas Flinkow 03.05.2018 07:42

Другие вопросы по теме