我正在我的数据库和我的C#代码之间实现一个缓存层.我们的想法是根据参数将某些数据库查询的结果缓存到查询中.数据库正在使用默认排序规则 - SQL_Latin1_General_CP1_CI_AS或者Latin1_General_CI_AS,我相信基于一些简短的谷歌搜索相当于相等,只是排序不同.
我需要一个.NET StringComparer,它可以给我相同的行为,至少对于相等测试和哈希码生成,正如数据库的排序规则所使用的那样.目标是能够在C#代码中的.NET字典中使用StringComparer来确定特定字符串键是否已经存在于缓存中.
一个非常简单的例子:
var comparer = StringComparer.??? // What goes here?
private static Dictionary<string, MyObject> cache =
    new Dictionary<string, MyObject>(comparer);
public static MyObject GetObject(string key) {
    if (cache.ContainsKey(key)) {
        return cache[key].Clone();
    } else {
        // invoke SQL "select * from mytable where mykey = @mykey"
        // with parameter @mykey set to key
        MyObject result = // object constructed from the sql result
        cache[key] = result;
        return result.Clone();
    }
}
public static void SaveObject(string key, …以下列表未正确排序(恕我直言):
$a = @( 'ABCZ', 'ABC_', 'ABCA' )
$a | sort
ABC_
ABCA
ABCZ
我方便的ASCII图表和Unicode C0控件和基本拉丁图表的下划线(低线)的序数为95(U + 005F).这是一个比大写字母AZ更高的数字.排序应该将字符串以下划线结尾.
Get-Culture是en-US
下一组命令符合我的期望:
$a = @( 'ABCZ', 'ABC_', 'ABCA' )
[System.Collections.ArrayList] $al = $a
$al.Sort( [System.StringComparer]::Ordinal )
$al
ABCA
ABCZ
ABC_
现在我创建一个包含相同3个字符串的ANSI编码文件:
Get-Content -Encoding Byte data.txt
65 66 67 90 13 10  65 66 67 95 13 10  65 66 67 65 13 10
$a = Get-Content data.txt
[System.Collections.ArrayList] $al = $a
$al.Sort( [System.StringComparer]::Ordinal )
$al
ABC_
ABCA
ABCZ
包含下划线/下线的字符串不再正确排序.我错过了什么?
编辑:
让我们参考这个例子#4:
'A' …我正在寻找一个方法,它将采用两个字符串并返回两者共有的字符数,例如:
"G010"和"G1820A"应返回3,因为两者中都存在G,0和1个字符.
如果两个字符都存在两次,则应按如下方式单独计算:
"G12AA"和"GAA2"应返回4,因为两者中都存在G,A,A和2个字符.
对此有何帮助?到目前为止,谷歌搜索并没有太大帮助.
我正在对元素列表进行排序:
var matchEle = listOfElements.Where(e => e.Properties().Any(p => p.Name.Contains("Key", Asking for IEqualityComparer))).First();
我习惯于直接使用 StringComparer、OrdinalIgnoreCase 或 CurrentCultureIgnoreCase,但是在这种情况下调用 Contains() 时,它会要求使用 IEqualityComparer。我想是因为数据结构/级别。我看到了如何设置 IEqualityComparer 的示例,例如
strEqualityComparer = new IEqualityComparer();
并为 strEqualityComparer 定义类,但我不确定除此之外。有人可以帮助我让 linq 语句处理忽略案例吗?
更新:我很清楚这是数据结构的示例:
listOfElements = [element1, element2, etc..]
element1.Properties = ["Prop1", "Key1", "Prop2", "Key2", etc.]
如果其任何属性具有包含关键字的值,我需要提取通过过滤器的元素,在本例中为“Key”,因此它不能是 .Equals 或 IndexOf。
根据StringComparer.OrdinalIgnoreCase属性的MSDN文档:
OrdinalIgnoreCase属性实际上返回从StringComparer类派生的匿名类的实例.
这是一个我不熟悉的功能 - 带继承的匿名类型吗?或者通过"匿名类",作者只是意味着"内部类派生自StringComparer客户端代码不可见"?
检查下面的更新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) …我有两个字符串" CZSczs" - " ?ŽŠ?žš"我希望在比较字符串时返回true.我尝试使用字符串比较,但它不起作用.
我一直在使用StringComparer.CurrentCultureIgnoreCase不区分大小写的比较和散列。但是在检查参考源之后,我发现它每次调用都会创建一个新实例(那么它不应该是一个静态函数吗?只是为了形式)。无论如何,我的问题是,当您需要进行多次比较(例如IEquality<T>实现)时,这样做是否有效:
// 2 instances per call
return StringComparer.CurrentCultureIgnoreCase.Equals(this.a, other.a)
  && StringComparer.CurrentCultureIgnoreCase.Equals(this.b, other.b) .. etc ..
或者可能:
public bool Equals(MyObj other)
{
  // 1 instance per call
  var equ = StringComparer.CurrentCultureIgnoreCase;
  return equ.Equals(this.a, other.a)
    && equ.Equals(this.b, other.b) .. etc ..
}
或者甚至缓存/池比较器,这样它们就不会在每次Equals()调用时创建?
// 1 instance per thread
[ThreadStatic]
private static StringComparer equ;
public bool Equals(MyObj other)
{
  if (equ == null) equ = StringComparer.CurrentCultureIgnoreCase;
  return equ.Equals(this.a, other.a)
    && equ.Equals(this.b, other.b) .. etc ..
}
对最佳实践有何感受? …
我正在寻找一个快速的.NET类/库,它具有支持通配符(*)AND incase-sensitivity的StringComparer.有任何想法吗?
我跑了这个:
void Main()
{
    List<string> strings = new List<string>{"aaa", "z", "a"};
    Console.WriteLine(string.Join("\n", strings.OrderBy(k => k)));
}
输出是:
a
z
aaa
这不可能是对的!我在期待
a
aaa
z
可能是什么问题呢?
stringcomparer ×10
c# ×8
.net ×4
linq ×3
string ×2
c#-4.0 ×1
collation ×1
powershell ×1
sortedlist ×1
sorting ×1
sql-server ×1