考虑T = string。
我很好奇它是否使用了类似:typeof(EqualityComparer<T>).GetInterface("IEqualityComparer<T>");
任何建议..
答案 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/")
。
如果false
为T
,则类string
会重载两个有问题的方法,并使用序数比较。因此,在这种情况下,它应该等同于System.String
。当然,System.StringComparer.Ordinal
是一个string
类,因此没有其他类可以从sealed
派生,并以某种奇怪的方式覆盖string
和Equals
。