web-dev-qa-db-fra.com

Convert.ToBoolean échoue avec la valeur "0"

J'essaie de convertir la valeur "0" (System.String) en sa représentation Boolean, telle que:

var myValue = Convert.ToBoolean("0"); // throwing an exception here

J'ai consulté la page MSDN , et dans le bloc exemple de code, j'ai trouvé les lignes suivantes:

ConvertToBoolean("0");
// ...
Unable to convert '0' to a Boolean.

Dans mon code, je convertis du System.String en Boolean comme ceci:

// will be OK, but ugly code
var myValue = Convert.ToBoolean(Convert.ToInt32("0"));
  • Existe-t-il un autre moyen de convertir le type Boolean avec un code si peu laid?
  • Pourquoi une telle exception se produit-elle? En raison de la conversion du type de référence System.String en valeur, le System.Boolean, mais System.Int32 est également un type de valeur, n'est-ce pas?
19
Secret

Cela se produit parce que Convert.ToBoolean attend l'un des éléments suivants:

Toute valeur autre n'est pas valide pour Boolean.

Vous avez déjà une approche propre:

var myValue = Convert.ToBoolean(Convert.ToInt32("0"));

Edit: Vous pouvez créer une méthode d'extension qui gérera quelques-uns de ces cas pour vous, tout en cachant la laideur du traitement de la conversion.

Cette extension fournit une interprétation très vague de Boolean:

  • "True" (String) = true
  • "False" (String) = false
  • "0" (String) = false
  • Toute autre chaîne = true

Code:

public static class Extensions
{
    public static Boolean ToBoolean(this string str)
    {
        String cleanValue = (str ?? "").Trim();
        if (String.Equals(cleanValue, "False", StringComparison.OrdinalIgnoreCase))
            return false;
        return
            (String.Equals(cleanValue, "True", StringComparison.OrdinalIgnoreCase)) ||
            (cleanValue != "0");
    }
}

Sinon, si vous souhaitez une approche plus stricte, qui suit les attentes du .NET Framework; puis utilisez simplement les instructions try/catch:

public static class Extensions
{
    public static Boolean ToBoolean(this string str)
    {
        try
        {
            return Convert.ToBoolean(str);
        }
        catch { }
        try
        {
            return Convert.ToBoolean(Convert.ToInt32(str));
        }
        catch { }
        return false;
    }
}

Bien que ce ne soit pas une approche propre ou jolie, elle garantit davantage de possibilités d'obtenir la valeur correcte. Et la classe Extensions est cachée de votre code de données/métier.

Au final, votre code de conversion est relativement simple à utiliser:

String myString = "1";
Boolean myBoolean = myString.ToBoolean();
54
Jesse
public static class BooleanParser
{
    public static bool SafeParse(string value)
    {
        var s = (value ?? "").Trim().ToLower();
        return s == "true" || s == "1";
    }
}

static readonly HashSet<string> _booleanTrueStrings = new HashSet<string> { "true", "yes", "1" };
static readonly HashSet<string> _booleanFalseStrings = new HashSet<string> { "false", "no", "0" };

public static bool ToBoolean(string value)
{
    var v = value?.ToLower()?.Trim() ?? "";
    if (_booleanTrueStrings.Contains(v)) return true;
    if (_booleanFalseStrings.Contains(v)) return false;
    throw new ArgumentException("Unexpected Boolean Format");
}
6
ChaosPandion

Puisqu'il s'agit vraiment de continuer à faire ces conversions, pourquoi ne pas utiliser une méthode d'extension?

public static class Extensions {
    public static bool ToBool(this string s) {
        return s == "0" ? false : true;
    }
}

et alors vous l'utiliseriez comme ceci:

"0".ToBool();

et maintenant, vous pouvez facilement étendre cette méthode pour traiter encore plus de cas si vous le souhaitez. 

3
Mike Perrenoud

Assez rapide et simple:

public static class Extensions
{
        static private List<string> trueSet = new List<string> { "true","1","yes","y" };

        public static Boolean ToBoolean(this string str)
        {
            try
            { return trueSet.Contains(str.ToLower()); }
            catch { return false; }
        }
}
1
user369122

Pour qu'une conversion réussisse, le paramètre value doit être égal à Boolean.TrueString , une constante dont la valeur est True, Boolean.FalseString , une constante dont la valeur est False ou doit être null. En comparant la valeur avec Boolean.TrueString et Boolean.FalseString, la méthode ignore la casse ainsi que les espaces blancs de début et de fin.

depuis MSDN

parce que Convert.ToBoolean attend un vrai si la valeur n'est pas zéro; sinon, faux. valeur numérique et True ou FalseString valeur.

1
Pyromancer

Si vous savez que ce serait un int, vous pouvez le convertir en int puis en bool. La suite va essayer de convertir en bool en essayant la chaîne puis en essayant un nombre.

public bool ToBoolean(string value)
{
  var boolValue = false;
  if (bool.TryParse(value, out boolValue ))
  {
    return boolValue;
  }

  var number = 0;
  int.TryParse(value, out number))
  return Convert.ToBoolean(number);
}
1
loopedcode

Voici un analyseur très pardonnant qui supprime le premier caractère:

public static class StringHelpers
{
    /// <summary>
    /// Convert string to boolean, in a forgiving way.
    /// </summary>
    /// <param name="stringVal">String that should either be "True", "False", "Yes", "No", "T", "F", "Y", "N", "1", "0"</param>
    /// <returns>If the trimmed string is any of the legal values that can be construed as "true", it returns true; False otherwise;</returns>
    public static bool ToBoolFuzzy(this string stringVal)
    {
        string normalizedString = (stringVal?.Trim() ?? "false").ToLowerInvariant();
        bool result = (normalizedString.StartsWith("y") 
            || normalizedString.StartsWith("t")
            || normalizedString.StartsWith("1"));
        return result;
    }
}
0
Mark Meuer