简体   繁体   English

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

[英]How do I safely cast a System.Object to a `bool` in C#?

I am extracting a bool value from a (non-generic, heterogeneous) collection.我正在从(非通用的、异构的)集合中提取一个bool值。

The as operator may only be used with reference types, so it is not possible to do use as to try a safe-cast to 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;

Is there something similar that can be done to safely cast an object to a value type without possibility of an InvalidCastException if, for whatever reason, the value is not a boolean?如果出于某种原因,该值不是布尔值,是否可以执行类似的操作来安全地将对象转换为值类型而不会出现InvalidCastException

There are two options... with slightly surprising performance:有两种选择......性能略有惊人:

  • Redundant checking:冗余检查:

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

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

The surprising part is that the performance of the second form is much worse than the first .令人惊讶的是, 第二种形式性能比第一种差很多

In C# 7, you can use pattern matching for this:在 C# 7 中,您可以为此使用模式匹配:

if (rawValue is bool value)
{
    // Use value here
}

Note that you still end up with value in scope (but not definitely assigned) after the if statement.请注意,在if语句之后,您仍然以作用域中的value (但未明确分配)结束。

Like this:像这样:

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

Unlike reference types, there's no fast way to try to cast to a value type without two casts.与引用类型不同,没有快速的方法可以尝试在没有两次强制转换的情况下强制转换为值类型。 (Or a catch block, which would be worse) (或者一个catch块,这会更糟)

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

You haven't defined what you want to have happen if rawValue is not convertible to bool.如果 rawValue 不能转换为 bool,你还没有定义你想要发生的事情。 Common choices are to return false, null, or throw an exception.常见的选择是返回 false、null 或抛出异常。 There's also the possibility of the string representation of rawValue to be convertible to a bool, such as Yes/No, True/False, 1/0, etc. rawValue 的字符串表示也有可能转换为 bool,例如 Yes/No、True/False、1/0 等。

I would use bool.TryParse to do the conversion.我会使用 bool.TryParse 进行转换。 This will succeed if rawValue is a bool or its string value is "True" or "False".如果 rawValue 是 bool 或其字符串值是“True”或“False”,这将成功。

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

You can cast it to a bool?您可以将其转换为bool? with the as keyword and check the HasValue property.使用as关键字并检查HasValue属性。

With C# 9 you can also simplify to:使用 C# 9,您还可以简化为:

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

Providing you don't actually need to keep a reference to the rawValue , here's a one-liner using the GetValueOrDefault() method of the Nullable<T> structure:如果您实际上不需要保留对rawValue的引用,这里是使用Nullable<T>结构的GetValueOrDefault()方法的单行:

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

You can also specify a default value using the method overload GetValueOrDefault(T) .您还可以使用方法重载GetValueOrDefault(T)指定默认值。

I used this check before doing something with object我在用对象做某事之前使用了这个检查

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

If the goal is to have true only if the raw object is boolean ' true ' then one-liner (rawValue as bool?)?? false如果目标是有真正只有在生对象是布尔“”,然后一行代码(rawValue as bool?)?? false (rawValue as bool?)?? false will do: (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`
bool value = (rawValue is null) ? false : (bool)rawValue.value;

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

你也可以试试 Convert.ToBoolean(rowValue);

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

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