简体   繁体   English

正确区分布尔? 和C#中的bool

[英]Correctly distinguish between bool? and bool in C#

I am trying to find out if a variable is either a simple bool or a Nullable<bool> . 我试图找出一个变量是一个简单的bool还是一个Nullable<bool>

It seems that 看起来

if(val is Nullable<bool>)

returns true for both bool and Nullable<bool> variables and 对于boolNullable<bool>变量都返回true

if(val is bool)

also returns true for both bool and Nullable<bool> . 对于boolNullable<bool>也返回true。

Basically, I am interesting in finding out if a simple bool variable is true OR if a Nullable<bool> variable is not null . 基本上,我很有兴趣找出一个简单的bool变量是否为 或者如果Nullable<bool>变量不为null

What's the way to do this? 这样做的方法是什么?

Here is the full code: 这是完整的代码:

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

The InstViewModel object: 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; }
}

The point of my code here is to find out if all of the object's values are null (more specifically, to find out any values that are not null and save them in a List<string> ). 这里我的代码的目的是找出所有对象的值是否为null (更具体地说,找出任何非null值并将它们保存在List<string> )。 This presents a complication in the lambda expression, however, when trying to distinguish between bool and bool? 然而,当试图区分boolbool?时,这会给lambda表达带来复杂性bool? types in my object (second Where statement). 我的对象中的类型(第二个Where语句)。

Additionally, since the object contains some string types as well, I am trying to exclude those in my first .Where statement (which I am probably not doing right at present as it doesn't seem to be working). 另外,由于对象也包含一些字符串类型,我试图在我的第一个.Where语句中排除那些(我目前可能做得不好,因为它似乎没有工作)。 But my main goal is to distinguish between bool and bool? 但我的主要目标是区分boolbool? types. 类型。

There is a simple way to check whether a variable is declared as T or T? 有一种简单的方法可以检查变量是否声明为TT? :

private static bool IsNullable<T>(T val)
{
    return false;
}

private static bool IsNullable<T>(T? val)
    where T : struct
{
    return true;
}

Usage: 用法:

bool? val = false;

if (IsNullable(val))
{
    ...
}

EDIT 编辑
Try the following code for edited question: 针对编辑的问题,请尝试以下代码:

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

Code for getting class instance values: 获取类实例值的代码:

// 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);
typeof(InstViewModel).GetProperties()
  .Select(prop => prop.GetValue(ivm, null))

At this point, you have a sequence of type object . 此时,您有一个类型object的序列。 Each element of that sequence will be an object that can be one of: 该序列的每个元素都是一个对象,可以是以下之一:

  1. An instance of a reference type. 引用类型的实例。
  2. A boxed instance of a value type. 值类型的盒装实例。
  3. null . null

The null case can happen either because you had a null value for a property which was of reference type, or a null value for a property that was a nullable value type; null情况可能发生,因为您具有引用类型的属性的null值,或者属于可空值类型的属性的null值; there's no way to tell the difference at here. 在这里没有办法区分。 Likewise there's no way to tell the difference between a boxed bool that came from a bool value or a boxed bool that came from a bool? 同样没有办法告诉盒装的区别bool从一来到bool值或盒装bool说从来到bool? value. 值。

You need to examine the type of the property, not the property's value: 您需要检查属性的类型,而不是属性的值:

isNullableProperty = property.PropertyType.IsGenericType
  && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);

But to just filter to only bool and bool? 但只过滤到boolbool? then: 然后:

typeof(InstViewModel).GetProperties()
  .Where(
     prop => prop.PropertyType == typeof(bool)
     || prop.PropertyType == typeof(bool?))

You can distinguish the boolean and nullable boolean properties before you evaluate them. 在评估布尔属性和可空布尔属性之前,可以区分它们。 Then there is no need to worry about whether they evaluate to a bool or a Nullable<bool> : 然后就不用担心他们是否评估为boolNullable<bool>

var nullableBooleanProperties = typeof(InstViewModel).Where(prop => prop.PropertyType == typeof(bool?));

Then you can simply write these out to a list of strings: 然后你可以简单地将这些写出来到一个字符串列表:

var values = nullableBooleanProperties.Select(prop => prop.GetValue(ivm)).Where(val => val != null).Select(val => val.ToString());

Putting these together gives: 将这些放在一起给出:

var values = typeof(InstViewModel).Where(prop => prop.PropertyType == typeof(bool?))
    .Select(prop => prop.GetValue(ivm)).Where(val => val != null)
    .Select(val => val.ToString())
    .ToList();

which gives you the list you are looking for. 它为您提供了所需的列表。

This is a response to the initial question - ignore this. 这是对最初问题的回应 - 忽略这一点。

When you "box" a nullable value (so you put it in an object ), it is transformed in its underlying type ( bool in your case) or in null ... So if you have 当你“装箱”一个可以为空的值(所以你把它放在一个object )时,它会被转换为它的底层类型(在你的情况下是bool )或者是null ...所以如果你有

bool? value = true;
object value2 = value; 

now value2.GetType() == typeof(bool) 现在value2.GetType() == typeof(bool)

According to your question 根据你的问题

Basically, I am interest ed in finding out if a simple bool variable is true OR if a Nullable variable is not null. 基本上,我的兴趣在找出如果一个简单的布尔变量为真,或者如果可空变量不为空。

  • to tell if a simple boolVariable is true 判断一个简单的boolVariable是否为真

      if(boolVariable){ //bool variable, not nullable } 
  • to tell if your nullableVariable is not null 判断你的nullableVariable是否为null

      if(nullableVariable.HasValue){ //a nullable variable is not null } 
  • to tell if nullable bool variable is true or/and not null, use the ?? 要告诉可空的bool变量是真还是/而不是null,请使用?? operator 操作者

     if(variable??false){ //then I'm sure that this is not null and has value=true } 

So in definitive you can use the following code for both nullable bool and bool variables 因此,在确定的情况下,您可以将以下代码用于可空的bool和bool变量

     if(variables!=null &&variables!=false){/*This may give a warning message but it works*/}

or 要么

   if(((bool?)variable)??false){
      /*variable is not null and is true*/
    }

Try this: 尝试这个:

((bool?)val).HasValue

This will return true , if val is a bool or if val is a bool? 如果valbool valbool? ,这将返回true bool? which value is not null . 哪个值不为null

On the other hand, 另一方面,

!((bool?)val).HasValue

will only return true if val is bool? 如果val是bool?只会返回true bool? and its value is null . 的值是null

Will not that test suffice in your case? 在你的情况下,那个测试不够吗?

Try this 试试这个

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM