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

时间:2015-06-04 10:26:20

标签: c# reflection

我试图找出变量是简单的bool还是Nullable<bool>

似乎

if(val is Nullable<bool>)

boolNullable<bool>变量以及

都返回true
if(val is bool)
对于boolNullable<bool>

也会返回true。

基本上,我很有兴趣找出一个简单的bool变量是 true OR 如果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>中)。但是,当尝试区分对象中的boolbool?类型(第二个Where语句)时,这会在lambda表达式中出现并发症。

此外,由于该对象也包含一些字符串类型,我试图在我的第一个.Where语句中排除那些(我目前可能做得不好,因为它似乎不起作用) 。但我的主要目标是区分boolbool?类型。

8 个答案:

答案 0 :(得分:11)

有一种简单的方法可以检查变量是否声明为TT?

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

答案 1 :(得分:4)

获取类实例值的代码:

// 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 :(得分:4)

-(void)viewWillDisappear:(BOOL)animated

此时,您有一个typeof(InstViewModel).GetProperties() .Select(prop => prop.GetValue(ivm, null)) 类型的序列。该序列的每个元素都是一个对象,可以是以下之一:

  1. 参考类型的实例。
  2. 值类型的盒装实例。
  3. object
  4. null情况可能发生,因为您具有引用类型的属性的空值,或者属于可空值类型的属性的空值;在这里没有办法区分它们。同样,我们也无法区分来自null值的盒装bool或来自bool值的盒装bool。< / p>

    您需要检查属性的类型,而不是属性的值:

    bool?

    但只过滤到isNullableProperty = property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>); bool,然后:

    bool?

答案 3 :(得分:3)

在评估布尔属性和可空布尔属性之前,可以区分它们。然后,无需担心他们是评估为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();

为您提供所需的列表。

答案 4 :(得分:2)

这是对最初问题的回答 - 请忽略此问题。

当您“装箱”一个可以为空的值(因此您将其放入object)时,它会在其基础类型(在您的情况下为bool)或null中进行转换。 ..所以,如果你有

bool? value = true;
object value2 = value; 

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

答案 5 :(得分:2)

根据你的问题

  

基本上,我很感兴趣 ed ,找出一个简单的bool变量是否为真或者Nullable变量是否为空。

  • 判断一个简单的boolVariable是否为真

     if(boolVariable){
          //bool variable, not nullable
     }
    
  • 判断你的nullableVariable是否为空

     if(nullableVariable.HasValue){
         //a nullable variable is not null
     }
    
  • 判断可以为空的bool变量是真还是/而不是null,使用??运算符

    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*/
    }

答案 6 :(得分:1)

试试这个:

((bool?)val).HasValue

这将返回true,如果valbool ,如果valbool?,则该值不是null !((bool?)val).HasValue

另一方面,

true
如果val为bool? 其值为null

将仅返回use Symfony\Component\Stopwatch\Stopwatch; include 'vendor/autoload.php'; $toClone = [ ['url' => 'http://github.com/symfony/symfony.git', 'dest' => 'C:\tmp\cloneR1'], ['url' => 'http://github.com/laravel/laravel.git', 'dest' => 'C:\tmp\cloneR2'], ['url' => 'http://github.com/rails/rails.git', 'dest' => 'C:\tmp\cloneR3'], ]; $end = count($toClone); $i = 0; $deferred = new React\Promise\Deferred(); $fClone = function (\React\EventLoop\Timer\Timer $timer) use (&$i, $deferred, &$toClone, $end) { $project = array_pop($toClone); $git = new \GitWrapper\GitWrapper(); $git->setTimeout(3600); $git->cloneRepository($project['url'], $project['dest']); $deferred->notify([$i++, $project['url']]); if ($end <= $i) { $timer->cancel(); $deferred->resolve(); } }; $stopwatch = new Stopwatch(); $stopwatch->start('run'); $loop = React\EventLoop\Factory::create(); $loop->addPeriodicTimer(1, $fClone); $deferred->promise()->then(function () use ($stopwatch) { echo 'DONE' . PHP_EOL; $event = $stopwatch->stop('run'); echo 'Run took ' . $event->getDuration() / 1000 . 'sec and ' . $event->getMemory() . ' bytes of memory'; }, null, function ($data) { echo 'RUN ' . $data[0] . ' - ' . $data[1] . PHP_EOL; }); $loop->run();

在你的情况下,那个测试不够吗?

答案 7 :(得分:1)

试试这个

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