[英]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 对于
bool
和Nullable<bool>
变量都返回true
if(val is bool)
also returns true for both bool
and Nullable<bool>
. 对于
bool
和Nullable<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?
然而,当试图区分
bool
和bool?
时,这会给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?
但我的主要目标是区分
bool
和bool?
types. 类型。
There is a simple way to check whether a variable is declared as T
or T?
有一种简单的方法可以检查变量是否声明为
T
或T?
: :
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: 该序列的每个元素都是一个对象,可以是以下之一:
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?
但只过滤到
bool
和bool?
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>
: 然后就不用担心他们是否评估为
bool
或Nullable<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?
如果
val
是bool
或 val
是bool?
,这将返回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.