EqualityComparer <t> .Default如何在内部工作?</t>

时间:2013-01-31 11:29:22

标签: c#

考虑T = string。

我很好奇它是否使用了类似:typeof(EqualityComparer<T>).GetInterface("IEqualityComparer<T>");

的东西

任何建议..

2 个答案:

答案 0 :(得分:9)

礼貌反思:

public static EqualityComparer<T> Default
{
    get
    {
        EqualityComparer<T> defaultComparer = EqualityComparer<T>.defaultComparer;
        if (defaultComparer == null)
        {
            defaultComparer = EqualityComparer<T>.CreateComparer();
            EqualityComparer<T>.defaultComparer = defaultComparer;
        }
        return defaultComparer;
    }
}

private static EqualityComparer<T> CreateComparer()
{
    RuntimeType c = (RuntimeType) typeof(T);
    if (c == typeof(byte))
    {
        return (EqualityComparer<T>) new ByteEqualityComparer();
    }
    if (typeof(IEquatable<T>).IsAssignableFrom(c))
    {
        return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(GenericEqualityComparer<int>), c);
    }
    if (c.IsGenericType && (c.GetGenericTypeDefinition() == typeof(Nullable<>)))
    {
        RuntimeType type2 = (RuntimeType) c.GetGenericArguments()[0];
        if (typeof(IEquatable<>).MakeGenericType(new Type[] { type2 }).IsAssignableFrom(type2))
        {
            return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(NullableEqualityComparer<int>), type2);
        }
    }
    if (c.IsEnum && (Enum.GetUnderlyingType(c) == typeof(int)))
    {
        return (EqualityComparer<T>) RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType) typeof(EnumEqualityComparer<int>), c);
    }
    return new ObjectEqualityComparer<T>();
}

因此,您可以看到T = string,它将返回GenericEqualityComparer<string>

答案 1 :(得分:2)

EqualityComparer<T>.Default通过调用由virtual定义的Equals(object)方法GetHashCode()System.Object来工作,但可能会被{{1}覆盖,也可能不会被覆盖}。

请注意,由于metod是T,因此可以使用比virtual更多派生类的实现。例如:

T
即使

也会返回EqualityComparer<object>.Default .Equals(new Uri("http://example.com/"), new Uri("http://example.com/"))

true

Object.ReferenceEquals(new Uri("http://example.com/"), new Uri("http://example.com/"))

都返回(object)new Uri("http://example.com/") == (object)new Uri("http://example.com/")

如果falseT,则类string会重载两个有问题的方法,并使用序数比较。因此,在这种情况下,它应该等同于System.String。当然,System.StringComparer.Ordinal是一个string类,因此没有其他类可以从sealed派生,并以某种奇怪的方式覆盖stringEquals