在 .Net 中,有没有一种方法可以将整数的数字转换为对应的字符串?

7

例如:

(1).SomeFunction().Equals("one")
(2).SomeFunction().Equals("two")

我只需要处理数字1-9,那么我应该使用switch/select语句吗?

更新 在这种情况下,我也不需要本地化。

更新2 这是我最终使用的代码:

Private Enum EnglishDigit As Integer
    zero
    one
    two
    three
    four
    five
    six
    seven
    eight
    nine
End Enum

(CType(someIntThatIsLessThanTen, EnglishDigit)).ToString()
7个回答

11

你觉得枚举怎么样?

enum Number
{
    One = 1, // default value for first enum element is 0, so we set = 1 here
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
}

那么您可以输入类似以下内容...

((Number)1).ToString()

如果你需要本地化,则可以为每个枚举值添加一个DescriptionAttribute。该属性的Description属性将存储资源项键的名称。

enum Number
{
    [Description("NumberName_1")]
    One = 1, // default value for first enum element is 0, so we set = 1 here 

    [Description("NumberName_2")]
    Two,

    // and so on...
}
以下函数将从属性中提取Description属性的值。
public static string GetDescription(object value)
{
    DescriptionAttribute[] attributes = null;
    System.Reflection.FieldInfo fi = value.GetType().GetField(value.ToString());
    if (fi != null)
    {
        attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
    }

    string description = null;
    if ((attributes != null) && (attributes.Length > 0))
    {
        description = attributes[0].Description;
    }

    return description;
}

可以按以下方式调用:

GetDescription(((Number)1))

从那里,您可以从资源文件中提取相关值,或者如果返回了null,则只需调用.ToString()

编辑

一些评论者指出(我必须同意),仅使用枚举值名称引用本地化字符串会更简单。


3
列举是一种简单的解决方案,除非你需要本地化 :) - OregonGhost
我更新了我的答案,包括一个可以本地化的解决方案。 - Richard Ev
2
正如我在回答中建议的那样,我宁愿使用枚举名称和枚举值的名称作为资源字符串的关键字。这似乎比阅读代码时要理解另一个属性更容易。但是你提出的方式也可以行得通,我猜想。顺便提一下,即使travis不需要,我建议在你的枚举中添加“Zero”,因为0是任何枚举的有效值,即使没有明确定义 :) - OregonGhost
1
没错,但是就像我之前说过的那样,在这种情况下,我永远不需要除了英语以外的任何东西 :-) - travis
1
@travis: 对你来说没问题,但由于这个答案将在互联网上长期存在,其他人可能会发现这些附加信息很有用,所以即使这超出了你的需求范围,它也会改善答案的质量 :) 顺便说一下,很多人曾经认为他们永远不需要除英语之外的任何东西(或者大于640K的任何内容):D 如果我还没点赞的话,我现在就给这个回答点赞了 :) - OregonGhost
显示剩余3条评论

4
创建一个字符串字典:
string[] digits = new string[] 
{
   "zero",
   "one",
   "two",
   ...
};

string word = digits[digit];

1
为什么只停留在1-9呢...
C# 版本的方式与 Squeak Smalltalk 相同,适用于所有数字,包括 vigintillion:
    public static String AsWords(this int aNumber) {
        var answer = "";
        if (aNumber == 0) return "zero";
        if (aNumber < 0) {
            answer = "negative";
            aNumber = Math.Abs(aNumber);
        }

        var thousands = new[] {"", "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion","octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion"};
        var thousandCount = 0;
        while (aNumber > 0) {
            var underOneThousandName = ThreeDigitName(aNumber % 1000);
            aNumber = aNumber / 1000;
            if(underOneThousandName != "") {
                if (answer != "") answer = "," + answer;
                answer = underOneThousandName + " " + thousands[thousandCount] + answer;
            }
            thousandCount += 1;
        }
        return answer;
    }

    private static string ThreeDigitName(int aNumberLessThanOneThousand) {
        if (aNumberLessThanOneThousand == 0) return "";
        var units = new[] {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eightteen", "nineteen"};
        var answer = "";
        if (aNumberLessThanOneThousand > 99) {
            answer = units[(aNumberLessThanOneThousand / 100) - 1] + " hundred";
            if (aNumberLessThanOneThousand % 100 != 0)
                answer += " " + ThreeDigitName(aNumberLessThanOneThousand % 100);
            return answer;
        }
        if (aNumberLessThanOneThousand < 20) return units[aNumberLessThanOneThousand -1];
        var multiplesOfTen = new[] {"twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
        answer += multiplesOfTen[(aNumberLessThanOneThousand / 10)-2];
        if (aNumberLessThanOneThousand % 10 != 0) answer += "-" + units[(aNumberLessThanOneThousand % 10)-1];
        return answer;
    }

哈哈,对于我的目的来说有些过度了。 :-) - travis
把它放进一个库里,以便稍后使用 ;) - Hupperware
对于这个好的解决方案点赞,尽管还有另一种不容易本地化的解决方案:例如,法语中的数字99是quatre-vingt-dix-neuf(字面意思是四二十十九),甚至德语中简单的21也是如此(einundzwanzig,字面意思是一和二十)。不幸的是,这个问题没有简单的解决方案 :-/ - OregonGhost

1

使用查找表,数组就可以了。它不比枚举慢,而且更容易本地化。

编辑

Andrey的代码示例就是我所建议的,尽管我认为称其为字典有点令人困惑。


我希望能听到一些关于这个踩票的解释,除非这只是策略游戏。 - Steven Sudit

1

如果您不需要本地化,我建议使用Richard Ev的解决方案。但是,如果需要本地化,我建议将十个数字名称添加到资源文件中,例如NumberName_0NumberName_9。这样,在查找数字时,您只需加载名称为String.Format("NumberName_{0}", mydigit)的资源。

顺便说一下,同样的技术也适用于可本地化的枚举名称或描述。


资源表对我来说很有意义,但我会在启动时将所有十个值加载到数组中。 - Steven Sudit
2
我们可以将OregonGhost的资源字符串加载到Andrey的数组中,然后我认为我们会有所收获。 - Jeffrey L Whitledge
1
@Jeffrey L Whitledge:当然你可以把它们加载到数组中,但是每次用户更改语言环境时(如果你的应用支持即时切换),你都得这样做。那就多了一件容易被忘记的事情,所以如果每次加载资源字符串没有引入性能问题,我不会费心去做这个 :) - OregonGhost
True。应用程序还应该在决定懒惰或急切资源加载之前检查用户是否在闪存驱动器或磁盘上运行。 ;) - Jeffrey L Whitledge
@Jeffrey L Whitledge:实际上不是这样的。那会是过早优化,就像将值加载到数组中一样;)别误会我的笑话,我建议恰恰相反:除非证明它是瓶颈,否则要懒惰。这样可以节省很多时间。区别在于:你必须:1.创建数组,2.通过加载字符串来填充数组(每当文化变化时),3.访问数组以获取字符串。我只需要:1.加载字符串。完成。如果您使用分析器证明此字符串加载需要太长时间(对于应用程序而言),我同意使用数组。这就是我的观点:) - OregonGhost

0
如果您正在使用2008:
public static String AsWord(this int aNumber) {
    return ((Number) aNumber).ToString();
}

enum Number {
    One = 1,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
}

0

我认为没有内置函数可以做到这一点。我会使用选择语句。


为什么选择使用select/case而不是查找? - Steven Sudit

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