【问题标题】:string.Empty.StartsWith(((char)10781).ToString()) always returns true?string.Empty.StartsWith(((char)10781).ToString()) 总是返回true?
【发布时间】:2010-12-25 23:20:59
【问题描述】:

我试图处理以下字符:⨝ (http://www.fileformat.info/info/unicode/char/2a1d/index.htm)

如果你检查是否以这个字符开头的空字符串,它总是返回true,这没有任何意义!这是为什么呢?

// visual studio 2008 hides lines that have this char literally (bug in visual studio?!?) so i wrote it's unicode instead.
char specialChar = (char)10781;
string specialString = specialChar.ToString();

// prints 1
Console.WriteLine(specialString.Length);

// prints 10781
Console.WriteLine((int)specialChar);

// prints false
Console.WriteLine(string.Empty.StartsWith("A"));

// both prints true WTF?!?
Console.WriteLine(string.Empty.StartsWith(specialString));
Console.WriteLine(string.Empty.StartsWith(((char)10781).ToString()));

【问题讨论】:

    标签: c# .net string unicode char


    【解决方案1】:

    您可以使用ordinal StringComparison 修复此错误:

    来自 MSDN 文档:

    当您指定任一 StringComparison.Ordinal 或 StringComparison.OrdinalIgnoreCase, 字符串比较将是 非语言的。也就是说,特征 那些特定于自然的 制作时语言被忽略 比较决策。这意味着 决策基于简单字节 比较并忽略大小写或 等价表是 由文化参数化。因此, 通过将参数显式设置为 StringComparison.Ordinal 或 StringComparison.OrdinalIgnoreCase, 您的代码通常会提高速度,增加 正确性,并且变得更加 可靠。

        char specialChar = (char)10781;
    
    
        string specialString = Convert.ToString(specialChar);
    
        // prints 1
        Console.WriteLine(specialString.Length);
    
        // prints 10781
        Console.WriteLine((int)specialChar);
    
        // prints false
        Console.WriteLine(string.Empty.StartsWith("A"));
    
        // prints false
        Console.WriteLine(string.Empty.StartsWith(specialString, StringComparison.Ordinal));
    

    【讨论】:

    • Culture-sensitive-comparison-by-default 似乎是对最小意外原则的重大灾难性违反。是否有任何经验法则可以确定哪些方法需要 StringComparison 才能获得“正常”的序数行为,哪些不需要?
    • @bobince-你见过这个问题吗-stackoverflow.com/questions/72696/…
    【解决方案2】:

    不错的 unicode 故障 ;-p

    我不知道为什么会这样,但很有趣:

    Console.WriteLine(string.Empty.StartsWith(specialString)); // true
    Console.WriteLine(string.Empty.Contains(specialString)); // false
    Console.WriteLine("abc".StartsWith(specialString)); // true
    Console.WriteLine("abc".Contains(specialString)); // false
    

    我猜这有点像Jon mentioned at devdays 的非连接字符;一些字符串函数看到它,而有些则没有。如果它没有看到它,这将变成“(某些字符串)是否以空字符串开头”,这是 always true。

    【讨论】:

      【解决方案3】:

      这样做的根本原因是默认字符串比较是区域设置感知的。这意味着使用区域设置数据表进行比较(包括相等性)。

      许多(如果不是大多数)Unicode 字符对于许多语言环境都没有价值,因此不存在(或存在,但匹配任何内容,或什么都不存在)。

      请参阅 Michael Kaplan 的博客“Sorting It All Out”上有关字符权重的条目。 This series of blogs 包含大量背景信息(API 是原生的,但是——据我所知——.NET 中的机制是相同的)。

      快速版本:这是一个复杂的领域,很难进行正确的预期(普通语言)比较,这往往会导致与您的语言之外的字形代码点发生奇怪的事情。

      【讨论】:

        猜你喜欢
        • 2013-08-06
        • 2017-05-10
        • 2013-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多