如何在C#中安全地将System.Object转换为bool?

88

我正在从一个(非泛型、异构)集合中提取一个bool值。

as运算符只能用于引用类型,因此无法使用 as尝试将其安全转换为bool

// This does not work: "The as operator must be used with a reference type ('bool' is a value type)"
object rawValue = map.GetValue(key);
bool value = rawValue as bool;

是否有类似的方法可以安全地将对象强制转换为值类型,而不会出现InvalidCastException,如果由于任何原因该值不是布尔类型?

11个回答

162

有两种选择,对性能有一定意外表现:

  • 冗余检查:

    if (rawValue is bool)
    {
        bool x = (bool) rawValue;
        ...
    }
    
  • 使用可空类型:

  • bool? x = rawValue as bool?;
    if (x != null)
    {
        ... // use x.Value
    }
    

令人惊讶的是,第二种形式的性能比第一种差得多

在C# 7中,可以使用模式匹配来实现:

if (rawValue is bool value)
{
    // Use value here
}
请注意,if语句后仍然可以在作用域中访问value(但不一定已分配值)。

我发现 C# 文档对解释 'is' 运算符很有帮助。https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/operators/is - Lee Cichanowicz

21

就像这样:

if (rawValue is bool) {
    bool value = (bool)rawValue;
    //Do something
} else {
    //It's not a bool
}

与引用类型不同的是,尝试将值类型强制转换为另一种类型时没有快速的方法,需要进行两次转换(或使用更差的catch块)。


1
@SLaks:请参考我的和kalusbyskov的答案,以避免使用两个转换。虽然这并没有真正帮助到你。 - Jon Skeet

9

使用 C# 9 也可以简化为:

if(rawValue is true)
{
    //do stuff
}

这会先检查对象是否为 bool,如果不是则返回 false 吗? - Riscie

8
bool value;
if(rawValue is bool)
  value = (bool)rawValue;
else {
  // something is not right...

5

如果rawValue无法转换为bool,您尚未定义要发生什么。常见选择是返回false、null或抛出异常。另外,rawValue的字符串表示形式也可能可转换为bool,例如Yes/No、True/False、1/0等。

我会使用bool.TryParse来进行转换。如果rawValue是bool类型或其字符串值为"True"或"False",则此方法将成功转换。

bool result;
if (!bool.TryParse(rawValue as string, out result))
{
    // you need to decide what to do in this case
}

4
您可以使用as关键字将其转换为bool?类型,并检查HasValue属性。

1

如果您不需要保留对rawValue的引用,可以使用Nullable<T>结构的GetValueOrDefault()方法来实现一行代码:

bool value = (map.GetValue(key) as bool?).GetValueOrDefault();

您还可以使用方法重载GetValueOrDefault(T)指定默认值。


1
如果目标是仅在原始对象为布尔值“true”时返回true,则一行代码 (rawValue as bool?)?? false 可以实现:
object rawValue=null
(rawValue as bool?)?? false
false
rawValue="some string"
(rawValue as bool?)?? false
false
rawValue=true
(rawValue as bool?)?? false
true
rawValue="true"
(rawValue as bool?)?? false
false
rawValue=false
(rawValue as bool?)?? false
false
rawValue=""
(rawValue as bool?)?? false
false
rawValue=1
(rawValue as bool?)?? false
false
rawValue=new Dictionary<string,string>()
(rawValue as bool?)?? false
false`

0
bool value = (rawValue is null) ? false : (bool)rawValue.value;

如果rawValue为null,则value将为false,否则value将接收正确的布尔值。

0

在处理对象之前,我使用了这个检查。

if(myCrazyObject.GetType().Equals(typeof(bool)))
{
   //do smt with it
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接