我们最近将所有项目从.NET 3.5升级到.NET 4.我遇到了一个相当奇怪的问题string.IndexOf().
我的代码显然略有不同,但在调查问题的过程中,我发现调用IndexOf()一个字符串本身返回1而不是0.换句话说:
string text = "\xAD\x2D"; // problem happens with "-dely N.China", too;
int index = text.IndexOf(text); // see update note below.
Run Code Online (Sandbox Code Playgroud)
给我一个索引1而不是0.关于这个问题需要注意几点:
问题似乎与这些连字符有关(第一个字符是Unicode软连字符,第二个字符是常规连字符).
我已经仔细检查过,这不会发生在.NET 3.5中,而是发生在.NET 4中.
更改IndexOf()要进行序数比较可以解决问题,因此出于某种原因,默认情况下会忽略第一个字符IndexOf.
有谁知道为什么会这样?
编辑
对不起,伙计们,在原帖上做了一些东西,并在那里得到了隐藏的短跑两次.我已经更新了字符串,只要将其粘贴到正确的编辑器中,就应该返回1而不是2的索引.
更新:
将原始问题字符串更改为每个实际字符清晰可见的字符串(使用转义).这有点简化了问题.
我知道之前已经注意到这个问题,或多或少简洁,但我仍然创建这个新线程,因为我在编写单元测试时再次遇到了这个问题.
默认的字符串比较(即文化相关的区分大小写的比较,我们得到有string.CompareTo(string),Comparer<string>.Default,StringComparer.CurrentCulture,string.Compare(string, string)等)违反及物当字符串包含连字符(或减号,我说的是普通的U + 002D字符).
这是一个简单的复制品:
static void Main()
{
const string a = "fk-";
const string b = "-fk";
const string c = "Fk";
Console.WriteLine(a.CompareTo(b)); // "-1"
Console.WriteLine(b.CompareTo(c)); // "-1"
Console.WriteLine(a.CompareTo(c)); // "1"
var listX = new List<string> { a, b, c, };
var listY = new List<string> { c, a, b, };
var listZ = new List<string> { b, c, a, };
listX.Sort();
listY.Sort();
listZ.Sort();
Console.WriteLine(listX.SequenceEqual(listY)); // "False" …Run Code Online (Sandbox Code Playgroud) 检查下面的更新3 我发现我遇到的问题与.Net 4.0,4.0客户端和4.5的c#字符串比较器的已知严重问题有关,这将导致字符串列表的排序顺序不一致(导致输出依赖在输入的顺序和使用的排序算法).该问题于2012年12月向微软报告,并以"不会修复"结束.可以使用一种解决方法,但速度慢得多,对于大型集合来说几乎不实用.
在实现不可变的PatriciaTrie时,我想将其性能与System.Collections.Generic.SortedList进行比较.我使用以下文件https://github.com/rkapsi/patricia-trie/blob/master/src/test/resources/org/ardverk/collection/hamlet.txt来创建用于测试的输入词表.
当使用Comparer<string>.Default或StringComparer.InvariantCulture作为密钥比较器插入c#SortedList中的每个单词时,使用常规搜索方法无法检索成功插入的多个条目(例如,ContainsKey返回false),但密钥在列表中显示为通过迭代列表观察.
更奇怪的是,比较器在将从排序列表中检索到的密钥与无法找到的搜索密钥进行比较时返回值"0" ContainsKey.
下面的完整示例演示了我的系统上的这个问题.
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
// the problem is possibly related to comparison.
var fail = true;
var comparer = fail ? StringComparer.InvariantCulture : StringComparer.Ordinal;
// read hamlet (contains duplicate words)
var words = File
.ReadAllLines("hamlet.txt")
.SelectMany(l => l.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
.Select(w => w.Trim())
.Where(w => !string.IsNullOrEmpty(w))
.Distinct(comparer) …Run Code Online (Sandbox Code Playgroud)