Convert.ToBoolean和Boolean.Parse不接受0和1。

85
为什么在解析布尔值时,0/1是不可接受的?
在解析任何整数类型值时,它接受要解析的数字字符串。(如果.NET可以解析字符串"One hundred million two hundred and sixty five thousand eight hundred and sixty five",我会感到惊讶)。
那么布尔值有什么特别之处?根据我的经验,它们本质上是将0作为false和非零作为true......
是否有BCL方法来解析这样的字符串,如果没有,为什么?
注意:我忘记在一个字符串中指定"0"和"1"。不过有趣的是,如果已经是一个int类型,则它按照我预期的方式工作。也许这引起了混淆。
7个回答

85

0和(非零)不等于“false”和“true”,它们只是C语言选择的表示方法。其他语言使用0表示true,-1表示false,或者完全不同的方案。布尔值不是0或1,而是true或false。

它还应该处理“yes”和“no”,“off”和“on”以及所有其他类似布尔值的事物吗?在哪里划线呢?


3
谢谢!这就是我想要的,一个关于为什么的解释。如果确实有一些语言使用0表示true,-1表示false,我认为它们可能存在问题,但这也是不自动假设某些开发人员可能盲目使用的一个很好的理由。 - Brett Allen
90
好的,是的。它应该可以处理开/关的是/否。 - WEFX
3
进一步解释为什么有些语言使用0表示真,-1表示假,需要考虑它们的二进制表示:0000000011111111 - MCattle
8
@MCattle: WTH?11111111听起来比00000000或者-1更假吗?个人认为这是一个定义的问题,谈论个人喜好有点无意义,但是仅仅从二进制表示来看并没有增强我的直觉... - Mike Fuchs
5
我认为有一个约定:0=假,其他任何值都是真(通常为1,但如果你喜欢也可以为-1)。所以我会说00000是假的,1是真的,1111111是非常真的!;) @Aric,你能告诉我0=true是用什么语言表示的吗?我脑海中唯一想到的例子是在shell中,当程序完成时通常返回(0),但实际上这是一个错误代码(erro=0 -> error=false,因此ok)。 - José Ramón
显示剩余7条评论

35

什么使布尔值特殊?在我的经验中,它们本质上是0表示假,非零表示真...

那是一种实现细节,与此毫不相关。

true 是一个布尔值。 false 是一个布尔值。其他任何值都不是。

如果您想解析某些内容,以便字符串 "0" 评估为 false,而任何其他内容都评估为 true,您可以使用:

!mystr.Equals("0");

不错的简洁解决方案,我喜欢! - RemarkLima
10
字符串 "true" 和 "false" 是字符串,而不是布尔值。然而,当将它们转换为布尔值时,没有人似乎会有问题认识到它们的含义。如果我们足够聪明地认识到 "true" 的意思是 true,那么我认为我们也足够聪明地认识到 "1" 和 1 的意思是 true。并且,如果程序员明确请求进行转换,我们也足够聪明地认识到 "on" 和 "yes" 是肯定的,并且可以安全地转换为 true。 - Rikaelus

22

下面展示的共享FormatHelper类提供了一个简单的解决方案,使用两个重载方法StringToBoolean的变体。

FormatHelper.StringToBoolean(String value)
FormatHelper.StringToBoolean(String value, Boolean NullOrEmptyDefault)

两种变体都提供了不区分大小写的字符串匹配。

1) 从字符串到布尔型的常规转换,将空字符串或null字符串默认为false

以下示例将导致一个boolean值为false

 Boolean myBool = FormatHelper.StringToBoolean("");
 Boolean myBool = FormatHelper.StringToBoolean("0");
 Boolean myBool = FormatHelper.StringToBoolean("false");
 Boolean myBool = FormatHelper.StringToBoolean("False");
 Boolean myBool = FormatHelper.StringToBoolean("no");
 Boolean myBool = FormatHelper.StringToBoolean("off");

所有其他字符串值将导致 Boolean 值为 true,例如:-

 Boolean myBool = FormatHelper.StringToBoolean("1");
 Boolean myBool = FormatHelper.StringToBoolean("true");
 Boolean myBool = FormatHelper.StringToBoolean("True");
 Boolean myBool = FormatHelper.StringToBoolean("yes");
 Boolean myBool = FormatHelper.StringToBoolean("xyz blah");

注意:请在下面的类中编辑BooleanStringOff的值,将更多(或更少)的false/off值包含其中。

2) 与上面的1)相同,但允许将默认值true作为第二个参数提供给转换函数。

String值为空或null时,将使用默认值。 如果丢失的字符串值需要表示为true状态,则此选项非常有用。

以下代码示例将返回true

 Boolean myBool = FormatHelper.StringToBoolean("",true);
以下代码示例将返回false
 Boolean myBool = FormatHelper.StringToBoolean("false",true);

这是FormatHelper类的代码

public class FormatHelper
{
    public static Boolean StringToBoolean(String str)
    {
        return StringToBoolean(str, false);
    }

    public static Boolean StringToBoolean(String str, Boolean bDefault)
    {
        String[] BooleanStringOff = { "0", "off", "no" };

        if (String.IsNullOrEmpty(str))
            return bDefault;
        else if(BooleanStringOff.Contains(str,StringComparer.InvariantCultureIgnoreCase))
            return false;

        Boolean result;
        if (!Boolean.TryParse(str, out result))
            result = true;

        return result;
    }
}

1
我已将此更新为C# 7及以上版本的扩展方法,并设置了默认值:https://gist.github.com/jamiehowarth0/5587d7d3731d58b10e0559c6e0efb4e1 - Jamie Howarth

10

很不幸,在.NET中这种情况经常发生。例如,我记不清是XML Serializer还是XmlConvert,但其中一个会因为True/False的大小写不正确而失败。

您可以通过整数进行往返来获得所需结果。

string s = "2";
int i = Convert.ToInt32(s);
bool b = Convert.ToBoolean(i);

在上面的情况下,任何非零值都将被视为true。

因此,我创建了一个名为ConversionStrategy的类,它考虑源类型和目标类型,并选择最理想(也最灵活)的转换策略来进行转换,我在许多地方都使用这个类。


2
被接受的答案在理论上听起来不错,但当你看到这样的东西时,真的没有任何合理化的解释。 - Kyle
更快的解决方案 - elle0087

7

您需要使用Convert.ToBoolean(int value)方法,不确定Parse方法的作用是什么 :-)

毫无用处的代码:

        int falseInt = 0;
        int trueInt = 1;

        bool falseBool;
        bool trueBool;

        if (bool.TryParse(falseInt.ToString(), out falseBool))
        {
            if (!falseBool)
            {
                MessageBox.Show("TryParse: False");
            }
        }

        if (bool.TryParse(trueInt.ToString(), out trueBool))
        {
            if (!trueBool)
            {
                MessageBox.Show("TryParse: True");
            }
        }

        falseBool = Convert.ToBoolean(falseInt);
        trueBool = Convert.ToBoolean(trueInt);

        if (!falseBool)
        {
            MessageBox.Show("Convert: False");
        }

        if (trueBool)
        {
            MessageBox.Show("Convert: True");
        }

5
如何看待这个内容?
  byte i = 1; //or 0
  bool myBool = BitConverter.ToBoolean(new byte[] { i }, 0)

0
回答这个问题可能很难。也许是因为微软那些心胸狭窄的开发人员有他们自己的原因?请勿对他们不敬,只是说他们没有考虑到它将被用于什么或如何使用它。我想不出为什么我的下面的扩展不适用于任何人。我的意思是布尔值要么是打开或关闭,真或假。在我看来,它基本上是二进制的。Int、Double、Char、Long、Byte等的解析方法更容易通过它们的解析方法进行宽容处理。
然而,请考虑以下情况;您正在查看对象中是否存在某个值。同样可以说以下内容...
string myvar = "empty"; //Or maybe = "NULL"
if (String.IsNullOrEmpty(myvar))
{
    //Should this be true?
}

无论如何,让我们简化一下。这是我的解决方案,使用扩展方法为字符串创建一个ToBoolean()方法。

using System.Linq;
public static bool ToBoolean(this string input)
{
    //Define the false keywords
    String[] bFalse = { "false", "0", "off", "no" };

    //Return false for any of the false keywords or an empty/null value
    if (String.IsNullOrEmpty(input) || bFalse.Contains(input.ToLower()))
        return false;

    //Return true for anything not false
    return true;
}

补充一下我的帖子,今天我碰巧遇到了关于这个主题的一些东西。即使是 SQL 也使用 1 和 0 处理布尔值。BOOL:零被视为假,非零值被视为真。 - Arvo Bowen

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