Правильно отличить bool? и bool в С#
Я пытаюсь выяснить, является ли переменная простой: bool
или Nullable<bool>
.
Кажется, что
if(val is Nullable<bool>)
возвращает true для переменных bool
и Nullable<bool>
и
if(val is bool)
также возвращает true для bool
и Nullable<bool>
.
В принципе, мне интересно узнать, является ли простая переменная bool
истиной ИЛИ, если переменная Nullable<bool>
не равна нулю.
Каким образом это сделать?
Вот полный код:
List<string> values = typeof(InstViewModel).GetProperties()
.Where(prop => prop != "SubCollection" && prop != "ID" && prop != "Name" && prop != "Level")
.Select(prop => prop.GetValue(ivm, null))
.Where(val => val != null && (val.GetType() != typeof(bool) || (bool)val == true)) //here I'm trying to check if val is bool and true or if bool? and not null
.Select(val => val.ToString())
.Where(str => str.Length > 0)
.ToList();
Объект InstViewModel
:
public class InstViewModel
{
public string SubCollection { get; set; }
public string ID { get; set; }
public string Name { get; set; }
public string Level { get; set; }
public bool Uk { get; set; }
public bool Eu { get; set; }
public bool Os { get; set; }
public Nullable<bool> Mobiles { get; set; }
public Nullable<bool> Landlines { get; set; }
public Nullable<bool> UkNrs { get; set; }
public Nullable<bool> IntNrs { get; set; }
}
Точка моего кода здесь заключается в том, чтобы узнать, являются ли все значения объекта null
(точнее, для определения любых значений, которые не являются нулевыми, и сохраняют их в List<string>
). Это представляет собой усложнение в выражении лямбда, однако, при попытке различить типы bool
и bool?
в моем объекте (второй оператор Where
).
Кроме того, поскольку объект также содержит некоторые типы строк, я пытаюсь исключить их в первом операторе .Where
(который, вероятно, сейчас не работает правильно, поскольку он, похоже, не работает). Но моя главная цель - различать типы bool
и bool?
.
Ответы
Ответ 1
Код для получения значений экземпляра класса:
// create class instance
InstViewModel model = new InstViewModel()
{
Uk = true,
UkNrs = false,
};
// check all boolean fields are false or null
bool isAllNullOrFalse = (from property in typeof(InstViewModel).GetProperties()
let type = property.PropertyType
let isBool = type == typeof(bool)
where isBool || type == typeof(bool?)
let value = property.GetValue(model)
select value == null || (isBool && bool.Equals(value, false))).All(e => e);
Console.WriteLine("All values are null or false = {0}", isAllNullOrFalse);
Ответ 2
Существует простой способ проверить, объявлена ли переменная как T
или T?
:
private static bool IsNullable<T>(T val)
{
return false;
}
private static bool IsNullable<T>(T? val)
where T : struct
{
return true;
}
Использование:
bool? val = false;
if (IsNullable(val))
{
...
}
ИЗМЕНИТЬ
Попробуйте следующий код для отредактированного вопроса:
var boolProps = typeof (InstViewModel).GetProperties()
.Where(prop => prop.PropertyType == typeof(bool))
.Select(prop => (bool)prop.GetValue(ivm, null))
.Select(v => v ? v.ToString() : String.Empty);
var nullableBoolProps = typeof(InstViewModel).GetProperties()
.Where(prop => prop.PropertyType == typeof(bool?))
.Select(prop => (bool?)prop.GetValue(ivm, null))
.Select(v => v.HasValue ? v.ToString() : String.Empty);
List<string> values = boolProps.Concat(nullableBoolProps)
.Where(str => str.Length != 0)
.ToList();
Ответ 3
typeof(InstViewModel).GetProperties()
.Select(prop => prop.GetValue(ivm, null))
На этом этапе у вас есть последовательность типов object
. Каждый элемент этой последовательности будет объектом, который может быть одним из:
- Пример ссылочного типа.
- Вставной экземпляр типа значения.
-
null
.
Случай null
может произойти либо потому, что у вас есть нулевое значение для свойства, которое имеет ссылочный тип, либо значение null для свойства, которое является типом значений с нулевым значением; нет никакого способа сказать разницу здесь. Точно так же нет способа рассказать разницу между коробкой bool
, которая исходила из значения bool
или в коробке bool
, которая была получена из значения bool?
.
Вам нужно изучить тип свойства, а не значение свойства:
isNullableProperty = property.PropertyType.IsGenericType
&& property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
Но просто отфильтровать только bool
и bool?
, затем:
typeof(InstViewModel).GetProperties()
.Where(
prop => prop.PropertyType == typeof(bool)
|| prop.PropertyType == typeof(bool?))
Ответ 4
Вы можете отличить логические и обнуляемые логические свойства перед их оценкой. Тогда нет необходимости беспокоиться о том, оценивают ли они значение bool
или Nullable<bool>
:
var nullableBooleanProperties = typeof(InstViewModel).Where(prop => prop.PropertyType == typeof(bool?));
Затем вы можете просто записать их в список строк:
var values = nullableBooleanProperties.Select(prop => prop.GetValue(ivm)).Where(val => val != null).Select(val => val.ToString());
Объединяя их вместе, получаем:
var values = typeof(InstViewModel).Where(prop => prop.PropertyType == typeof(bool?))
.Select(prop => prop.GetValue(ivm)).Where(val => val != null)
.Select(val => val.ToString())
.ToList();
который дает вам список, который вы ищете.
Ответ 5
Это ответ на исходный вопрос - игнорируйте это.
Когда вы "вставляете" значение с нулевым значением (поэтому вы помещаете его в object
), оно преобразуется в его базовом типе (bool
в вашем случае) или в null
... Итак, если у вас есть
bool? value = true;
object value2 = value;
теперь value2.GetType() == typeof(bool)
Ответ 6
По вашему вопросу
В принципе, мне интересно узнать, истинна ли простая переменная bool или если переменная Nullable не равна null.
-
чтобы узнать, истинна ли простая boolVariable
if(boolVariable){
//bool variable, not nullable
}
-
чтобы узнать, не является ли ваш nullableVariable нулевым
if(nullableVariable.HasValue){
//a nullable variable is not null
}
-
чтобы указать, является ли переменная bool переменной null равной true или/или не равна нулю, используйте оператор ??
if(variable??false){
//then I'm sure that this is not null and has value=true
}
Итак, в окончательном варианте вы можете использовать следующий код для переменных с нулевым значением bool и bool
if(variables!=null &&variables!=false){/*This may give a warning message but it works*/}
или
if(((bool?)variable)??false){
/*variable is not null and is true*/
}
Ответ 7
Попробуйте следующее:
((bool?)val).HasValue
Это вернет true
, если val
является bool
или, если val
является bool?
, значение которого не равно null
.
С другой стороны,
!((bool?)val).HasValue
будет возвращать только true
, если val bool?
и его значение null
.
Не будет ли этого теста достаточно в вашем случае?
Ответ 8
Попробуйте это
List<string> values = typeof(InstViewModel).GetProperties()
.Select(prop => new { N = prop.Name, T = prop.PropertyType, V = prop.GetValue(ivm, null) })
.Where(prop => prop.N != "SubCollection" && prop.N != "ID" && prop.N != "Name" && prop.N != "Level")
.Where(val => (val.V != null && val.T.IsAssignableFrom(typeof(Nullable<bool>))) || Convert.ToBoolean(val.V))
.Select(val => val.V.ToString())
.Where(str => str.Length > 0)
.ToList();