将 Y 或 N 转换为布尔值 C#

18

只是为了整洁起见,我想知道是否可以将Y或N转换为bool类型?就像这样;

bool theanswer = Convert.ToBoolean(input);

较长的版本:

bool theanswer = false;
switch (input)
{
   case "y": theanswer = true; break;
   case "n": theanswer = false; break
}

2
你希望算法在字符串不是 "y" 或 "n" 的情况下失败吗? - Richard J. Ross III
我正在考虑尝试捕获异常。 - wonea
3
没有内置支持。我推测这是因为 y/n 是_本地化_信息(是/否),取决于当前的文化背景。 - sisve
10个回答

46

不,这方面没有内置的功能。

然而,鉴于您想将默认值设置为false,您可以直接使用:

bool theAnswer = (input == "y");

(这里括号只是为了清楚起见。)

你可能希望考虑使它不区分大小写,考虑到你的问题文本和你所拥有的代码之间的差异。一种做法是:

bool theAnswer = "y".Equals(input, StringComparison.OrdinalIgnoreCase);
请注意,使用指定的字符串比较可以避免创建新字符串,并且您不需要担心文化问题...除非您当然想执行区分文化的比较。还请注意,我将字面值作为方法调用的“目标”,以避免在输入为null时抛出NullReferenceException。

11
第二个例子中对输入为空的优雅处理方式不错,我要记住这点。 - Luc
2
(input ?? "").Equals("y", StringComparison.OrdinalIgnoreCase); 使意图清晰,我们检查变量的值是否等于某些常量而不是相反。这就是C++中的if (NULL==ptr)辩论。 - Muhammad Hasan Khan
你会失去 null 值,只能得到布尔值。 - Prageeth godage
1
@Prageethgodage:我不理解你的评论... OP没有指定任何关于可空值的要求。他们明确要求一个bool,根据我的第二句话判断,我怀疑在某个时候有一条评论表明他们想默认为false。当然,这可能不是你的具体情况。 - Jon Skeet

8
bool theanswer = input.ToLower() == "y";

在比较字符串时,使用.ToLower被认为是不好的习惯。更好的选择是使用equals函数。你的方法可能有效,但equals更好。另外,你的代码无法处理输入为空的情况(当输入为空时,在ToLower上会导致空引用异常)。 - Gertjan
太棒了,谢谢。我想多了解如何构建这类表达式的方法。 - wonea
2
@Gertjan - 请提供一个链接,以便考虑最佳实践,而不是做出一概而论的陈述。根据应用程序的需求,我认为在执行这样的代码片段时,可能会出现NullReferenceException异常。 - Joel Etherton
@Joel Etherton:我手头没有资料,但通常的逻辑告诉你,如果没有以正确的方式应用到所有变量,使用 .ToLowers 可能会导致严重的错误。FXCop 在使用 .ToLower 时会发出警告,并建议使用 ToUpperInvariant。我不知道 equals 函数的内部工作原理,但使用 .ToLower() 比较将为比较创建临时字符串。因此,可能使用 .ToLower(或 ToUpper)会导致额外的内存使用。另外,处理 null 的操作位于函数内部,使您自己的代码更加整洁。 - Gertjan
1
@Joel Etherton - NullReferenceException 在你的代码中始终是一个错误,因此绝对不应该被期望。如果 null 是无效的,则应使用 ArgumentNullException 或合同失败标记。这样更容易追踪。曾经尝试过在没有行号的情况下跟踪 NullReferenceException 的来源吗? - Greg Beech
@Greg Beech - 是的,唯一让它变得困难的是当它跨越不同的线程时。我并不一定不同意你或者@Gertjan,但我总是乐意阅读任何愿意提供的文档。 - Joel Etherton

5
创建一个字符串的扩展方法,执行第二个算法中指定的类似操作,从而简化您的代码。
public static bool ToBool(this string input)
{
    // input will never be null, as you cannot call a method on a null object
    if (input.Equals("y", StringComparison.OrdinalIgnoreCase))
    {
         return true;
    }
    else if (input.Equals("n", StringComparison.OrdinalIgnoreCase))
    {
         return false;
    }
    else
    {
         throw new Exception("The data is not in the correct format.");
    }
}

并调用代码:

if (aString.ToBool())
{
     // do something
}

1
很好的扩展方法使用,但也许最好对布尔类进行解析(就像Int.Parse一样)。 - Gertjan
1
你不能对一个无法实例化的类进行扩展,换句话说,你不能对静态类进行扩展。 - Richard J. Ross III
使用StartsWith而不是Equals有什么原因吗?我认为“不是很多”可能与“true”一样无效 :) (我还建议根据我的答案使用StringComparison。如果您确实要使用input.ToLower(),那么我至少只会调用它一次。) - Jon Skeet
我知道我晚了7年,但是你的评论(和代码)是错误的;input确实可以为null。扩展方法只是语法糖,实际调用等同于if (ExtensionClass.ToBool(aString)){ // do something } - Joshua Webb

5

4

这个怎么样?

bool theanswer = input.Equals("Y", StringComparison.OrdinalIgnoreCase);

或者使用更安全的版本。

bool theanswer = "Y".Equals(input, StringComparison.OrdinalIgnoreCase);

1
如果输入为空,它会给你一个错误。最好使用对 "y" 的 equals,因为它不可能为空。 - Gertjan

0

DotNetPerls有一个方便的类,用于解析各种字符串布尔值。

/// <summary>
/// Parse strings into true or false bools using relaxed parsing rules
/// </summary>
public static class BoolParser
{
    /// <summary>
    /// Get the boolean value for this string
    /// </summary>
    public static bool GetValue(string value)
    {
       return IsTrue(value);
    }

    /// <summary>
    /// Determine whether the string is not True
    /// </summary>
    public static bool IsFalse(string value)
    {
       return !IsTrue(value);
    }

    /// <summary>
    /// Determine whether the string is equal to True
    /// </summary>
    public static bool IsTrue(string value)
    {
       try
       {
            // 1
            // Avoid exceptions
            if (value == null)
            {
                return false;
            }

            // 2
            // Remove whitespace from string
            value = value.Trim();

            // 3
            // Lowercase the string
            value = value.ToLower();

            // 4
            // Check for word true
            if (value == "true")
            {
                return true;
            }

            // 5
            // Check for letter true
            if (value == "t")
            {
                return true;
            }

            // 6
            // Check for one
            if (value == "1")
            {
                return true;
            }

            // 7
            // Check for word yes
            if (value == "yes")
            {
                return true;
            }

            // 8
            // Check for letter yes
            if (value == "y")
            {
                return true;
            }

            // 9
            // It is false
            return false;
        }
        catch
        {
            return false;
        }
    }
}

被调用;

BoolParser.GetValue("true")
BoolParser.GetValue("1")
BoolParser.GetValue("0")

通过添加参数重载以接受对象,这可能进一步改进。


我认为这两个静态方法应该像这样成为扩展方法:public static bool GetValue(this string value) => IsTrue(value); public static bool IsFalse(this string value) => !IsTrue(value); - Brent Rittenhouse

0

还是这个?

bool CastToBoolean(string input)
{
    return input.Equals("Y", StringComparison.OrdinalIgnoreCase);
}

0

我遇到了同样的问题,但是用另一种方式解决了。

bool b=true; 
        decimal dec; 
        string CurLine = "";        
        CurLine = sr.ReadLine();
        string[] splitArray = CurLine.Split(new Char[] { '=' });
        splitArray[1] = splitArray[1].Trim();
        if (splitArray[1].Equals("Y") || splitArray[1].Equals("y")) b = true; else b = false;
        CurChADetails.DesignedProfileRawDataDsty1.Commen.IsPad = b;

0

Wonea在DotNetPerls中提供了一个“IsTrue”源代码示例。以下是两个更简短的版本:

public static bool IsTrue(string value)
{
    // Avoid exceptions
    if (value == null)
        return false;

    // Remove whitespace from string and lowercase it.
    value = value.Trim().ToLower();

    return value == "true"
        || value == "t"
        || value == "1"
        || value == "yes"
        || value == "y";
}

或:

private static readonly IReadOnlyCollection<string> LOWER_TRUE_VALUES = new string[] { "true", "t", "1", "yes", "y" };

public static bool IsTrue(string value)
{
    return value != null
        ? LOWER_TRUE_VALUES.Contains(value.Trim().ToLower())
        : false;
}

如果你想要更简短(虽然不太美观),你可以将它压缩成两行,像这样:

private static readonly IReadOnlyCollection<string> LOWER_TRUE_VALUES = new string[] { "true", "t", "1", "yes", "y" };
public static bool IsTrue(string value) => value != null ? LOWER_TRUE_VALUES.Contains(value.Trim().ToLower()) : false;

-1
class Program
{
    void StringInput(string str)
    {
        string[] st1 = str.Split(' ');

        if (st1 != null)
        {
            string a = str.Substring(0, 1);
            string b=str.Substring(str.Length-1,1);

             if(
                a=="^" && b=="^" 
                || a=="{" && b=="}" 
                || a=="[" && b=="]"
                ||a=="<" && b==">" 
                ||a=="(" && b==")"
                )

            {
                Console.Write("ok Formate correct");
            }
            else
            {
                Console.Write("Sorry incorrect formate...");
            }
        }
    }
    static void Main(string[] args)
    {
        ubaid: ;
        Program one = new Program();
        Console.Write("For exit Press N ");
        Console.Write("\n");
        Console.Write("Enter your value...=");
        string ub = Console.ReadLine();

        if (ub == "Y" || ub=="y" || ub=="N" || ub=="n" )
        {
            Console.Write("Are your want to Exit Y/N: ");
            string ui = Console.ReadLine();
            if (ui == "Y" || ui=="y")
            {
                return;
            }
            else
            {
                goto ubaid;
            }

        }
        one.StringInput(ub);           
        Console.ReadLine();
        goto ubaid;
    }
}

我的想法是制作一些小而简洁的东西,这段代码太多了。 - wonea

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