正确区分bool?和布尔在 C#
Correctly distinguish between bool? and bool in C#
我想知道一个变量是简单的 bool
还是 Nullable<bool>
。
好像
if(val is Nullable<bool>)
returns bool
和 Nullable<bool>
变量和
都为真
if(val is bool)
对于 bool
和 Nullable<bool>
也 returns 正确。
基本上,我感兴趣的是找出一个简单的 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
(更具体地说,找出任何不为 null 的值并将它们保存在 List<string>
).然而,当试图区分我的对象中的 bool
和 bool?
类型时(第二个 Where
语句),这会在 lambda 表达式中带来复杂性。
此外,由于该对象也包含一些字符串类型,我试图在我的第一个 .Where
语句中排除那些(我目前可能没有做对,因为它似乎不是在职的)。但我的主要目标是区分 bool
和 bool?
类型。
这是对初始问题的回答 - 忽略它。
当您 "box" 一个可为 null 的值(所以您将其放在 object
中)时,它会转换为其基础类型(在您的情况下为 bool
)或 null
...所以如果你有
bool? value = true;
object value2 = value;
现在value2.GetType() == typeof(bool)
有一种简单的方法可以检查一个变量是声明为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();
获取 class 个实例值的代码:
// 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))
此时,您有一个 object
类型的序列。该序列的每个元素都是一个对象,可以是以下之一:
- 引用类型的实例。
- 值类型的盒装实例。
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?))
试试这个:
((bool?)val).HasValue
这将 return true
,如果 val
是 bool
或 如果 val
是bool?
哪个值不是 null
.
另一方面,
!((bool?)val).HasValue
只会 return true
如果 val 是 bool?
和 它的值是 null
.
这个测试对你来说还不够吗?
根据你的问题
Basically, I am interested in finding out if a simple bool variable is true OR if a Nullable variable is not null.
判断一个简单的 boolVariable 是否为真
if(boolVariable){
//bool variable, not nullable
}
判断您的 nullableVariable 是否不为 null
if(nullableVariable.HasValue){
//a nullable variable is not null
}
判断可空布尔变量是否为真or/and不为空,使用??
运算符
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*/
}
试试这个
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();
您可以在计算布尔值和可为 null 的布尔值属性之前区分它们。那么就无需担心它们的计算结果是 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();
这会为您提供所需的列表。
我想知道一个变量是简单的 bool
还是 Nullable<bool>
。
好像
if(val is Nullable<bool>)
returns bool
和 Nullable<bool>
变量和
if(val is bool)
对于 bool
和 Nullable<bool>
也 returns 正确。
基本上,我感兴趣的是找出一个简单的 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
(更具体地说,找出任何不为 null 的值并将它们保存在 List<string>
).然而,当试图区分我的对象中的 bool
和 bool?
类型时(第二个 Where
语句),这会在 lambda 表达式中带来复杂性。
此外,由于该对象也包含一些字符串类型,我试图在我的第一个 .Where
语句中排除那些(我目前可能没有做对,因为它似乎不是在职的)。但我的主要目标是区分 bool
和 bool?
类型。
这是对初始问题的回答 - 忽略它。
当您 "box" 一个可为 null 的值(所以您将其放在 object
中)时,它会转换为其基础类型(在您的情况下为 bool
)或 null
...所以如果你有
bool? value = true;
object value2 = value;
现在value2.GetType() == typeof(bool)
有一种简单的方法可以检查一个变量是声明为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();
获取 class 个实例值的代码:
// 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))
此时,您有一个 object
类型的序列。该序列的每个元素都是一个对象,可以是以下之一:
- 引用类型的实例。
- 值类型的盒装实例。
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?))
试试这个:
((bool?)val).HasValue
这将 return true
,如果 val
是 bool
或 如果 val
是bool?
哪个值不是 null
.
另一方面,
!((bool?)val).HasValue
只会 return true
如果 val 是 bool?
和 它的值是 null
.
这个测试对你来说还不够吗?
根据你的问题
Basically, I am interested in finding out if a simple bool variable is true OR if a Nullable variable is not null.
判断一个简单的 boolVariable 是否为真
if(boolVariable){ //bool variable, not nullable }
判断您的 nullableVariable 是否不为 null
if(nullableVariable.HasValue){ //a nullable variable is not null }
判断可空布尔变量是否为真or/and不为空,使用
??
运算符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*/
}
试试这个
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();
您可以在计算布尔值和可为 null 的布尔值属性之前区分它们。那么就无需担心它们的计算结果是 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();
这会为您提供所需的列表。