【问题标题】:Why String.Equals is returning false?为什么 String.Equals 返回 false?
【发布时间】:2014-11-17 21:24:26
【问题描述】:

我有以下 C# 代码(来自我正在使用的库)尝试查找比较指纹的证书。请注意,在以下代码中,mycert.ThumbprintcertificateThumbprint 都是字符串。

var certificateThumbprint = AppSettings.CertificateThumbprint;

var cert =
    myStore.Certificates.OfType<X509Certificate2>().FirstOrDefault(
      mycert => 
      mycert.Thumbprint != null && mycert.Thumbprint.Equals(certificateThumbprint)
      );

这无法找到带有指纹的证书,因为即使字符串相等,mycert.Thumbprint.Equals(certificateThumbprint) 也是 falsemycert.Thumbprint == certificateThumbprint 也返回 false,而 mycert.Thumbprint.CompareTo(certificateThumbprint) 返回 0。

我可能遗漏了一些明显的东西,但我不知道为什么 Equals 方法会失败。想法?

【问题讨论】:

  • 这可能是一个奇怪的问题......但是每个字符串的长度是否相同? (试图以某种方式查看是否有任何不可打印的字符)。
  • 来自string.CompareTo 文档:字符集包括可忽略的字符。 CompareTo 方法在执行区分区域性的比较时不考虑此类字符。例如,如果以下代码在 .NET Framework 4 或更高版本上运行,“animal”与“animal”的比较(使用软连字符或 U+00AD)表明这两个字符串是等价的。
  • @JonathonReinhart 我的引用表明CompareTo 将可忽略的字符排除在比较之外。这就是 CompareTo 返回 0 的原因。我认为这就是 vcsjones 的作用。
  • 请查看每个字符串的.ToCharArray(),并逐个字符地比较它们。几乎可以肯定存在细微的性格差异。如果字符串正在报告:字符串可能不相等
  • @PeterRitchie 第一行代码为var certificateThumbprint = AppSettings.CertificateThumbprint;,因此是我的问题。问题已解释there。而且你不喜欢即时运行问题吗,OP 已经有一个小时没有出现了。

标签: c# string comparison equality


【解决方案1】:

CompareTo 忽略某些字符:

static void Main(string[] args)
{
    var a = "asdas"+(char)847;//add a hidden character
    var b = "asdas";
    Console.WriteLine(a.Equals(b)); //false
    Console.WriteLine(a.CompareTo(b)); //0
    Console.WriteLine(a.Length); //6
    Console.WriteLine(b.Length); //5

   //watch window shows both a and b as "asdas"
}

(这里,添加到a 的字符是U+034F,结合Grapheme Joiner。)

因此,CompareTo 的结果不能很好地指示 Equals 中的错误。您的问题最可能的原因是隐藏字符。您可以检查长度以确定。

请参阅this 了解更多信息。

【讨论】:

  • 确实,certificateThumbprint 字符串的开头有两个 U+200E(从左到右标记)字符。删除它可以解决问题。
  • 在所有答案中,这是正确的一个。还有一些 cmets 也指出了正确的问题,包括链接到这个问题stackoverflow.com/questions/11115511/…。我会将其标记为已接受的答案。希望我也能为 cmets 做到这一点。
【解决方案2】:

有时当我们在数据库中插入数据时,它会存储一些空格,例如“question”。当您尝试将其与 "question" 进行比较时,它会返回 false。所以我的建议是:请检查数据库中的值或使用 Trim() 方法。

在您的情况下,请尝试: mycert.Thumbprint != null && mycert.Thumbprint.trim().equals(certificateThumbprint.trim())

如果存在任何记录,我认为它会返回 true。

【讨论】:

    【解决方案3】:

    您可能希望尝试使用String.Equals 的重载,它接受StringComparison 类型的参数。

    例如:

    myCert.Thumbprint.Equals(certificateThumbprint, StringComparison.[SomeEnumeration])
    


    其中[SomeEnumeration] 替换为以下枚举常量之一:

     - CurrentCulture
     - CurrentCultureIgnoreCase
     - InvariantCulture
     - InvariantCultureIgnoreCase
     - Ordinal
     - OrdinalIgnoreCase
    


    参考找到的 MSDN 文档 here

    【讨论】:

    • 我试过OrdinalIgnoreCase,结果是一样的(即假)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-18
    • 2014-03-11
    • 2019-07-12
    • 2012-08-24
    相关资源
    最近更新 更多