C# KeyValuePair不区分大小写的密钥比较

C# KeyValuePair不区分大小写的密钥比较,c#,C#,Edit:culture这些内部操作表明固定区域性OrdinalIgnoreCase最合适 KeyValuePair是密封的。如果我有vara=KeyValuePair(“foo”,1)和var b=KeyValuePair(“foo”,2)并且比较a.Key==b.Key,我将得到false 我想说实话。首先,我将KeyValuePairs包装在自定义类中: public class MyKeyValuePair { private KeyValuePair<string, in

Edit:culture这些内部操作表明固定区域性
OrdinalIgnoreCase
最合适

KeyValuePair是密封的。如果我有var
a=KeyValuePair(“foo”,1)
var b=KeyValuePair(“foo”,2)
并且比较
a.Key==b.Key
,我将得到false

我想说实话。首先,我将KeyValuePairs包装在自定义类中:

public class MyKeyValuePair
{
    private KeyValuePair<string, int> myKeyValuePair;
    public SyncItem(string Key, int Value)
    {
        myKeyValuePair = new KeyValuePair<string, int>(Key, Value);
    }

    public string Key { get { return myKeyValuePair.Key; } }
    public int Value { get { return myKeyValuePair.Value; } }           
}
公共类MyKeyValuePair
{
private KeyValuePair myKeyValuePair;
公共同步项(字符串键,int值)
{
myKeyValuePair=新的KeyValuePair(键,值);
}
公共字符串密钥{get{return myKeyValuePair.Key;}}
公共int值{get{return myKeyValuePair.Value;}}
}
我的第一个想法是可以在键的构造函数中添加
.ToLower()


有更好的方法吗?有正确的方法吗?我应该考虑哪些因素?

< P>而不是将它转换为小写,你可以使用而不是<代码>=< /代码>运算符。(因为您的密钥是字符串类型)

您可以使用:


您可以覆盖相等运算符
==
,因此每次需要比较两个键时,您不必调用
ToLower()
或任何其他自定义方法。非常干净流畅的方法

public static bool operator ==(KeyValuePair<string, int> myKeyValuePair a, KeyValuePair<string, int> myKeyValuePair b)
{
    // If both are null, or both are same instance, return true.
    if (System.Object.ReferenceEquals(a, b))
    {
        return true;
    }

    // If one is null, but not both, return false.
    if (((object)a == null) || ((object)b == null))
    {
        return false;
    }

    // Return true if the fields match:
    return a.Key.Equals(b.Key, StringComparison.CurrentCultureIgnoreCase);
}
公共静态布尔运算符==(KeyValuePair myKeyValuePair a,KeyValuePair myKeyValuePair b)
{
//如果两者都为null,或者都是同一实例,则返回true。
if(System.Object.ReferenceEquals(a,b))
{
返回true;
}
//如果其中一个为null,但不是两个都为null,则返回false。
如果(((对象)a==null)| |((对象)b==null))
{
返回false;
}
//如果字段匹配,则返回true:
返回a.Key.Equals(b.Key,StringComparison.CurrentCultureIgnoreCase);
}

我喜欢过载解决方案,但它需要通过

对@Jeppe Stig Nielsen的研究表明,
OrdinalIgnoreCase
最适合于我的比较

使用OrdinalIgnoreCase进行的比较在行为上是两个调用的组合:对两个字符串参数调用ToUpperInvariant,并进行顺序比较。[http://msdn.microsoft.com/en-us/library/ms973919.aspx]

基于这个引文,我选择了
返回这个.Key.ToUpperInvariant().GetHashCode()GetHashCode()
重载中选择code>

类实现

public class MyKeyValuePair
{
    private readonly KeyValuePair<string, int> myKeyValuePair;
    public MyKeyValuePair(string key, int value)
    {
        myKeyValuePair = new KeyValuePair<string, int>(key, value);
    }

    public string Key { get { return myKeyValuePair.Key; } }
    public int Value { get { return myKeyValuePair.Value; } }

    public static bool operator ==(MyKeyValuePair a, MyKeyValuePair b)
    {
        if (System.Object.ReferenceEquals(a, b))
        {
            return true;
        }
        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }
        return a.Key.Equals(b.Key, StringComparison.OrdinalIgnoreCase);
    }
    public static bool operator !=(MyKeyValuePair a, MyKeyValuePair b)
    {
        return !(a == b);
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }
        MyKeyValuePair p = obj as MyKeyValuePair;
        if ((object)p == null)
        {
            return false;
        }
        return this.Key == p.Key;
    }

    public bool Equals(MyKeyValuePair obj)
    {
        if ((object)obj == null)
        {
            return false;
        }
        return this.Key.Equals(obj.Key, StringComparison.OrdinalIgnoreCase);
    }

    public override int GetHashCode()
    {
        return this.Key.ToUpperInvariant().GetHashCode();
    }
}
公共类MyKeyValuePair
{
私有只读KeyValuePair myKeyValuePair;
公共MyKeyValuePair(字符串键,int值)
{
myKeyValuePair=新的KeyValuePair(键,值);
}
公共字符串密钥{get{return myKeyValuePair.Key;}}
公共int值{get{return myKeyValuePair.Value;}}
公共静态布尔运算符==(MyKeyValuePair a,MyKeyValuePair b)
{
if(System.Object.ReferenceEquals(a,b))
{
返回true;
}
如果(((对象)a==null)| |((对象)b==null))
{
返回false;
}
返回a.Key.Equals(b.Key,StringComparison.OrdinalIgnoreCase);
}
公共静态布尔运算符!=(MyKeyValuePair a,MyKeyValuePair b)
{
返回!(a==b);
}
公共覆盖布尔等于(对象对象对象)
{
if(obj==null)
{
返回false;
}
MyKeyValuePair p=obj作为MyKeyValuePair;
如果((对象)p==null)
{
返回false;
}
返回此.Key==p.Key;
}
公共布尔等于(MyKeyValuePair obj)
{
如果((对象)obj==null)
{
返回false;
}
返回此.Key.Equals(obj.Key,StringComparison.OrdinalIgnoreCase);
}
公共覆盖int GetHashCode()
{
返回此.Key.ToUpperInvariant().GetHashCode();
}
}
试验方法

public void MyKeyValuePairCaseInsensitiveKeyComparisonWorksCorrectly()
{
    var x = new MyKeyValuePair("testvalue", 5);
    var y = new MyKeyValuePair("testvalue", 6);
    var z = new MyKeyValuePair("testvalue", 7);

    Assert.True(x == x, "== identity");
    Assert.True((x == y) == (y == x), "equals commutative");
    Assert.True(x == y, "== if x == y");
    Assert.True(y == x, "== and y == z");
    Assert.True(x == z, "== then x equals z");
    for (var successive_invocations = 0; successive_invocations < 3; successive_invocations++)
    {
        Assert.True(x == y, "== successive invocations");
    }
    Assert.False(x == null);

    Assert.True(x.Equals(x), "equals identity");
    Assert.True(x.Equals(y) == y.Equals(x), "equals commutative");
    Assert.True(x.Equals(y), "equals if x == y");
    Assert.True(y.Equals(x), "equals and y == z");
    Assert.True(x.Equals(z), "equals then x equals z");
    for (var successive_invocations = 0; successive_invocations < 3; successive_invocations++)
    {
        Assert.True(x.Equals(y), "equals successive invocations");
    }
    Assert.False(x.Equals(null));

    // show correct behavior
    var capi = "I";
    var lowi = "i";
    var capti = "İ";
    var lowti = "ı";

    Assert.True(capi.Equals(lowi, StringComparison.OrdinalIgnoreCase), "capi == lowi");
    Assert.False(capi.Equals(capti, StringComparison.OrdinalIgnoreCase), "capi != capti");
    Assert.False(capi.Equals(lowti, StringComparison.OrdinalIgnoreCase), "capi != lowti");

    Assert.False(lowi.Equals(capti, StringComparison.OrdinalIgnoreCase), "lowi != capti");
    Assert.False(lowi.Equals(lowti, StringComparison.OrdinalIgnoreCase), "lowi != lowti");

    Assert.False(capti.Equals(lowti, StringComparison.OrdinalIgnoreCase), "capti != lowti");

    //test actual behavior
    var a = new MyKeyValuePair(capi, 1);
    var b = new MyKeyValuePair(lowi, 2);
    var c = new MyKeyValuePair(capti, 3);
    var d = new MyKeyValuePair(lowti, 4);

    Assert.True(a.Equals(b), "a == b");
    Assert.False(a.Equals(c), "a != c");
    Assert.False(a.Equals(d), "a != d");

    Assert.False(b.Equals(c), "b != c");
    Assert.False(b.Equals(d), "b != d");

    Assert.False(c.Equals(d), "c != d");
}
public void MyKeyValuePaircaseinsensitiveKeyComparisonWorkScorectly()
{
var x=新的MyKeyValuePair(“testvalue”,5);
var y=新的MyKeyValuePair(“testvalue”,6);
var z=新的MyKeyValuePair(“testvalue”,7);
True(x==x,“==identity”);
True((x==y)=(y==x),“等于可交换”);
True(x==y,“==if x==y”);
True(y==x,“==和y==z”);
True(x==z,“==x=z”);
for(var连续调用=0;连续调用<3;连续调用++)
{
True(x==y,“==连续调用”);
}
Assert.False(x==null);
Assert.True(x.Equals(x),“Equals identity”);
Assert.True(x.Equals(y)==y.Equals(x),“Equals可交换”);
True(x.Equals(y),“如果x==y则等于”;
True(y.Equals(x),“Equals and y==z”);
Assert.True(x.Equals(z),“等于然后x等于z”);
for(var连续调用=0;连续调用<3;连续调用++)
{
True(x.Equals(y),“等于连续调用”);
}
Assert.False(x.Equals(null));
//举止端正
var capi=“I”;
var lowi=“i”;
var capti=“İ”;
var lowti=“ı”;
True(capi.Equals(lowi,StringComparison.OrdinalIgnoreCase),“capi==lowi”);
Assert.False(capi.Equals(capti,StringComparison.OrdinalIgnoreCase),“capi!=capti”);
Assert.False(capi.Equals(lowti,StringComparison.OrdinalIgnoreCase),“capi!=lowti”);
Assert.False(lowi.Equals(capti,StringComparison.OrdinalIgnoreCase),“lowi!=capti”);
Assert.False(lowi.Equals(lowti,StringComparison.OrdinalIgnoreCase),“lowi!=lowti”);
Assert.False(capti.Equals(lowti,StringComparison.OrdinalIgnoreCase),“capti!=lowti”);
//测试实际行为
var a=新的MyKeyValuePair(capi,1);
var b=新的MyKeyValuePair(低i,2);
var c=新的MyKeyValuePair(capti,3);
var d=新的MyKeyValuePair(lowti,4);
断言.True(a.Equals(b),“a==b”);
Assert.False(a.Equals(c),“a!=c”);
public class MyKeyValuePair
{
    private readonly KeyValuePair<string, int> myKeyValuePair;
    public MyKeyValuePair(string key, int value)
    {
        myKeyValuePair = new KeyValuePair<string, int>(key, value);
    }

    public string Key { get { return myKeyValuePair.Key; } }
    public int Value { get { return myKeyValuePair.Value; } }

    public static bool operator ==(MyKeyValuePair a, MyKeyValuePair b)
    {
        if (System.Object.ReferenceEquals(a, b))
        {
            return true;
        }
        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }
        return a.Key.Equals(b.Key, StringComparison.OrdinalIgnoreCase);
    }
    public static bool operator !=(MyKeyValuePair a, MyKeyValuePair b)
    {
        return !(a == b);
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }
        MyKeyValuePair p = obj as MyKeyValuePair;
        if ((object)p == null)
        {
            return false;
        }
        return this.Key == p.Key;
    }

    public bool Equals(MyKeyValuePair obj)
    {
        if ((object)obj == null)
        {
            return false;
        }
        return this.Key.Equals(obj.Key, StringComparison.OrdinalIgnoreCase);
    }

    public override int GetHashCode()
    {
        return this.Key.ToUpperInvariant().GetHashCode();
    }
}
public void MyKeyValuePairCaseInsensitiveKeyComparisonWorksCorrectly()
{
    var x = new MyKeyValuePair("testvalue", 5);
    var y = new MyKeyValuePair("testvalue", 6);
    var z = new MyKeyValuePair("testvalue", 7);

    Assert.True(x == x, "== identity");
    Assert.True((x == y) == (y == x), "equals commutative");
    Assert.True(x == y, "== if x == y");
    Assert.True(y == x, "== and y == z");
    Assert.True(x == z, "== then x equals z");
    for (var successive_invocations = 0; successive_invocations < 3; successive_invocations++)
    {
        Assert.True(x == y, "== successive invocations");
    }
    Assert.False(x == null);

    Assert.True(x.Equals(x), "equals identity");
    Assert.True(x.Equals(y) == y.Equals(x), "equals commutative");
    Assert.True(x.Equals(y), "equals if x == y");
    Assert.True(y.Equals(x), "equals and y == z");
    Assert.True(x.Equals(z), "equals then x equals z");
    for (var successive_invocations = 0; successive_invocations < 3; successive_invocations++)
    {
        Assert.True(x.Equals(y), "equals successive invocations");
    }
    Assert.False(x.Equals(null));

    // show correct behavior
    var capi = "I";
    var lowi = "i";
    var capti = "İ";
    var lowti = "ı";

    Assert.True(capi.Equals(lowi, StringComparison.OrdinalIgnoreCase), "capi == lowi");
    Assert.False(capi.Equals(capti, StringComparison.OrdinalIgnoreCase), "capi != capti");
    Assert.False(capi.Equals(lowti, StringComparison.OrdinalIgnoreCase), "capi != lowti");

    Assert.False(lowi.Equals(capti, StringComparison.OrdinalIgnoreCase), "lowi != capti");
    Assert.False(lowi.Equals(lowti, StringComparison.OrdinalIgnoreCase), "lowi != lowti");

    Assert.False(capti.Equals(lowti, StringComparison.OrdinalIgnoreCase), "capti != lowti");

    //test actual behavior
    var a = new MyKeyValuePair(capi, 1);
    var b = new MyKeyValuePair(lowi, 2);
    var c = new MyKeyValuePair(capti, 3);
    var d = new MyKeyValuePair(lowti, 4);

    Assert.True(a.Equals(b), "a == b");
    Assert.False(a.Equals(c), "a != c");
    Assert.False(a.Equals(d), "a != d");

    Assert.False(b.Equals(c), "b != c");
    Assert.False(b.Equals(d), "b != d");

    Assert.False(c.Equals(d), "c != d");
}