KeyValuePair的不区分大小写的键比较

时间:2013-07-24 15:02:12

标签: c#

编辑:文化这些内部操作建议不变文化 OrdinalIgnoreCase是最合适的。

KeyValuePair是密封的。如果我有var a = KeyValuePair<string,int>("foo",1)var b = KeyValuePair<string,int>("FOO",2)并且我比较a.Key == b.Key我会得到错误。

我想成真。首先,我将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; } }           
}

我的第一个想法是我可以在Key的构造函数中添加.ToLower()

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

4 个答案:

答案 0 :(得分:5)

您可以使用String.Equals Method (String, StringComparison)代替==运算符,而不是将其转换为小写。 (因为您的密钥是字符串类型)

a.Key.Equals(b.Key, StringComparison.CurrentCultureIgnoreCase)

答案 1 :(得分:3)

您可以覆盖相等运算符==,因此每次需要比较两个键时,您不必调用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);
}

答案 2 :(得分:1)

您可以使用String.Equals

a.Key.Equals(b.Key, StringComparison.InvariantCultureIgnoreCase)

答案 3 :(得分:0)

我喜欢重载解决方案,但需要通过http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

完成

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

使用OrdinalIgnoreCase进行的比较在行为上是两个调用的组合:在两个字符串参数上调用ToUpperInvariant,并进行Ordinal比较。 ”[http:// msdn .microsoft.com / EN-US /库/ ms973919.aspx]

根据此引文,我在return this.Key.ToUpperInvariant().GetHashCode();重载中选择了GetHashCode()

班级实施

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");
}