Wie kann ich ein System.Object sicher in einen Bool in C # umwandeln?

73

Ich extrahiere einen boolWert aus einer (nicht generischen, heterogenen) Sammlung.

Der asOperator darf nur mit Referenztypen verwendet werden, daher ist es nicht möglich, aseinen Safe-Cast zu verwenden, um 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;

Gibt es etwas Ähnliches, das getan werden kann, um ein Objekt sicher in einen Werttyp umzuwandeln, ohne dass die Möglichkeit besteht InvalidCastException, dass der Wert aus irgendeinem Grund kein Boolescher Wert ist?

Daniel Fortunov
quelle

Antworten:

134

Es gibt zwei Möglichkeiten ... mit etwas überraschender Leistung:

  • Redundante Überprüfung:

    if (rawValue is bool)
    {
        bool x = (bool) rawValue;
        ...
    }
    
  • Verwenden eines nullbaren Typs:

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

Der überraschende Teil ist, dass die Leistung der zweiten Form viel schlechter ist als die der ersten .

In C # 7 können Sie hierfür den Mustervergleich verwenden:

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

Beachten Sie, dass Sie valuenach der ifAnweisung immer noch im Gültigkeitsbereich (aber nicht definitiv zugewiesen) sind .

Jon Skeet
quelle
18

So was:

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

Im Gegensatz zu Referenztypen gibt es keine schnelle Möglichkeit, einen Werttyp ohne zwei Umwandlungen zu verwenden. (Oder ein Fangblock, der schlimmer wäre)

SLaks
quelle
1
@SLaks: In den Antworten von mir und kalusbyskov finden Sie Alternativen zur Verwendung von zwei Besetzungen. Nicht dass es wirklich hilft.
Jon Skeet
8
bool value;
if(rawValue is bool)
  value = (bool)rawValue;
else {
  // something is not right...
Webleeuw
quelle
5

Sie haben nicht definiert, was passieren soll, wenn rawValue nicht in bool konvertierbar ist. Häufig können Sie false, null oder eine Ausnahme zurückgeben. Es besteht auch die Möglichkeit, dass die Zeichenfolgendarstellung von rawValue in einen Bool konvertierbar ist, z. B. Ja / Nein, Richtig / Falsch, 1/0 usw.

Ich würde bool.TryParse verwenden, um die Konvertierung durchzuführen. Dies ist erfolgreich, wenn rawValue ein Bool ist oder sein Zeichenfolgenwert "True" oder "False" ist.

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

Sie können es bool?mit dem asSchlüsselwort in a umwandeln und die HasValueEigenschaft überprüfen .

Klaus Byskov Pedersen
quelle
1

Vorausgesetzt, Sie müssen keinen Verweis auf die behalten rawValue, ist hier ein Einzeiler, der die GetValueOrDefault()Methode der Nullable<T>Struktur verwendet:

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

Sie können auch einen Standardwert mithilfe der Methodenüberladung angeben GetValueOrDefault(T).

Nick W.
quelle
0

Ich habe diese Prüfung verwendet, bevor ich etwas mit dem Objekt gemacht habe

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

Wenn das Ziel darin besteht, nur dann true zu haben , wenn das Rohobjekt boolesch ' true ' ist, reicht ein Einzeiler aus (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`
dmitry
quelle
-1

Sie können auch einfach tun, wenn es passt:

if(rawValue is true)
{
    //do stuff
}
Falk
quelle
-3

Sie können auch Convert.ToBoolean (rowValue) ausprobieren.

user3934664
quelle
1
Dies löst eine Ausnahme aus, wenn der Typ nicht in einen Booleschen Wert konvertierbar ist, und es wird auch versucht, nicht-boolesche Werte in einen Booleschen Wert zu konvertieren, wenn dies möglich ist. Dies sollte nicht der Anforderungsstatus sein.
Servy
Hoppla. Ich habe hier also nicht aufgepasst. Vielen Dank!
user3934664