C# string.equals表示误报

C# string.equals表示误报,c#,asp.net,string,dataset,C#,Asp.net,String,Dataset,在将事件存储到事件管理系统中时,我还存储了更改的历史记录。因为项目指定了MySql的使用,而MySql触发器留下了一些需要改进的地方,所以我使用实际代码来检测更改。我使用以下代码行查看support notes字段是否已更改,并相应地添加历史记录: .... if (!String.Equals(OldEventInfo.supportNotes, NewEventInfo.supportNotes)) { ChangesMade.Add(new EventHistor

在将事件存储到事件管理系统中时,我还存储了更改的历史记录。因为项目指定了MySql的使用,而MySql触发器留下了一些需要改进的地方,所以我使用实际代码来检测更改。我使用以下代码行查看support notes字段是否已更改,并相应地添加历史记录:

    ....
    if (!String.Equals(OldEventInfo.supportNotes, NewEventInfo.supportNotes))
    {  ChangesMade.Add(new EventHistoryDataItem("support notes", OldEventInfo.supportNotes, NewEventInfo.supportNotes)); }
    ....
    EventsDataset eds = new EventsDataset();
    EventsDatasetTableAdapters.eventhistoryTableAdapter ehta = new EventsDatasetTableAdapters.eventhistoryTableAdapter();
    EventsDatasetTableAdapters.eventhistorydataTableAdapter ehdta = new EventsDatasetTableAdapters.eventhistorydataTableAdapter();
    Int64 HistoryId = Convert.ToInt64(ehta.InsertQuery(NewEventInfo.id.Value, DateTime.Now, UserId));

    eds.eventhistorydata.Clear();
    foreach (EventHistoryDataItem thisChange in ChangesMade)
    {
        EventsDataset.eventhistorydataRow newRow = (EventsDataset.eventhistorydataRow)eds.eventhistorydata.NewRow();
        newRow.eventHistoryId = HistoryId;
        newRow.field = thisChange.Field;
        newRow.oldValue = thisChange.OldValue;
        newRow.newValue = thisChange.NewValue;
        eds.eventhistorydata.AddeventhistorydataRow(newRow);
    }
    ehdta.Update(eds.eventhistorydata);
问题是,我得到的“支持说明”的历史记录在之前和之后具有相同的值。我已经研究了关于string.equals生成假返回的其他问题,并且我已经检查以确保前后字符串是相同的,并且它们是相同的。没有额外的空格、回车符或换行符。它们是二进制相同的。
那么,有什么好处呢?我的历史记录中记录的值从a变为B,但a和B是相同的,这是怎么结束的?

这是因为字符串编码不同,它们的字符串不相等,尽管它们包含相同的字符


如果您想比较这两个字符串,并且它们来自不同的来源,并且您不担心编码问题,那么使用string.Normalize()方法对它们进行比较,它会起作用。

因此字符串确实不同。仔细的二进制比较表明,字符串的一个版本中有回车符,而另一个版本中没有回车符。我不得不直接从数据库中取出数据来比较它们

select hex(OldValue), hex(NewValue) from EventHistoryData where Id = 39645;
这表明,在应该有新行的地方,字符串的一个版本有新行的Windows实现(carinereturn+LineFeed=\r\n=x0D0A),另一个版本有新行的Unix实现(LifeFeed=\n=x0A)。 在我的Windows IIS机器和Unix机器上的MySql服务器之间的某个地方,字符串的新行被转换为Unix实现。 最简单的解决方案是将比较更改为忽略回车。由于Windows换行符是\r\n而Unix和Mac换行符是\r\n,因此比较字符串最简单的方法是删除\r\n,将所有换行符转换为Unix版本。所以

if (!String.Equals(OldEventInfo.supportNotes, NewEventInfo.supportNotes))
变成

if (!String.Equals(OldEventInfo.supportNotes.Replace("\r",""), NewEventInfo.supportNotes.Replace("\r","")))

我知道你说过没有空位也没有回车。但是空格和回车并不是唯一不能呈现的字符。编辑器无法呈现更多的字符。确认没有额外字符的一种方法是包含长度测试:
if(OldEventInfo.supportNotes.length!=NewEventInfo.supportNotes.length&&!String.Equals(OldEventInfo.supportNotes,NewEventInfo.supportNotes)){…}
如果它们是二进制相同的,那么它们的GetHashCode()应该返回相同的值。如果不是,那么无论出于什么原因,它们都是不相等的(比如行尾的不同或者沿着这些行的不同)。@StephenPorter——事实证明,你是对的,这意味着我撒谎了。我回去更仔细地看了看,实际上弦是不同的。在数据进入Unix服务器上的MySql和返回之间,Windows新行(回车+换行符-0D0A)变成了Unix新行(换行符-0A)。这导致字符串测试不相等。过一会儿我可能会删除这个问题。它原来是@AgapwIesu的翻版,很高兴你能弄明白:)自从我在Windows中开发、对接我的应用程序并部署到Linux服务器后,我开始使用.NET Core时,就一直在努力解决这个问题。您遇到了行结束和路径问题哈哈。Michael,您知道string.Normalize对新行的特定平台实现有什么作用吗?我在谷歌上搜索了很多关于Unicode规范化的文章,但是没有任何东西能告诉我新行会发生什么。您可以模拟一个快速控制台应用程序,将不同版本的文本解析为不同的二进制编码并进行测试。我很好奇…好建议。我应该自己考虑的。我做了这样一个模型,并使其正常化,使回车和换行保持不变。回车符和换行符都存在于UTF-16中,这正是c#字符串所使用的,所以我猜它认为这两个字符都是“普通”unicode。但我不确定自己是否真正理解Unicode规范化的概念。无论如何,谢谢你帮我了解这件事。我打赌它会派上用场的。