88

I am extracting a bool value from a (non-generic, heterogeneous) collection.

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:

// 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?

Daniel Fortunov
  • 43,309
  • 26
  • 81
  • 106

11 Answers11

162

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:

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I found the C# docs helpful to explain the 'is' operator. https://learn.microsoft.com/en-US/dotnet/csharp/language-reference/operators/is – Lee Cichanowicz Aug 21 '23 at 13:01
21

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)

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 1
    @SLaks: See mine and kalusbyskov's answers for alternatives to using two casts. Not that it really helps. – Jon Skeet Dec 29 '09 at 14:48
8
bool value;
if(rawValue is bool)
  value = (bool)rawValue;
else {
  // something is not right...
Webleeuw
  • 7,222
  • 33
  • 34
8

With C# 9 you can also simplify to:

if(rawValue is true)
{
    //do stuff
}
Orace
  • 7,822
  • 30
  • 45
Falk
  • 99
  • 1
  • 4
5

You haven't defined what you want to have happen if rawValue is not convertible to bool. Common choices are to return false, null, or throw an exception. 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.

I would use bool.TryParse to do the conversion. This will succeed if rawValue is a bool or its string value is "True" or "False".

bool result;
if (!bool.TryParse(rawValue as string, out result))
{
    // you need to decide what to do in this case
}
Community
  • 1
  • 1
Jamie Ide
  • 48,427
  • 16
  • 81
  • 117
4

You can cast it to a bool? with the as keyword and check the HasValue property.

Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
1

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:

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

You can also specify a default value using the method overload GetValueOrDefault(T).

Nick W.
  • 181
  • 1
  • 5
1

If the goal is to have true only if the raw object is boolean 'true' then one-liner (rawValue as bool?)?? false will do:

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`
dmitry
  • 182
  • 1
  • 9
0

I used this check before doing something with object

if(myCrazyObject.GetType().Equals(typeof(bool)))
{
   //do smt with it
}
Project Mayhem
  • 439
  • 5
  • 12
0
bool value = (rawValue is null) ? false : (bool)rawValue.value;

if rawValue is null then value will be false, otherwise value will receive the correct boolean value.

Michael Hutter
  • 1,064
  • 13
  • 33
-3

You can also try Convert.ToBoolean(rowValue);

  • 1
    This will throw an exception if the type is not a convertible to a boolean, and it also will try to convert non-boolean values into a boolean if it can, which is not what the requirements state should happen. – Servy Aug 12 '14 at 18:16
  • Oops. I so was not paying attention here. Thanks! – user3934664 Aug 15 '14 at 16:41