Betrachte T = string.Wie funktioniert EqualityComparer <T> .Default intern?
Ich bin gespannt, ob es nutzt so etwas wie: typeof(EqualityComparer<T>).GetInterface("IEqualityComparer<T>");
Irgendwelche Vorschläge ..
Betrachte T = string.Wie funktioniert EqualityComparer <T> .Default intern?
Ich bin gespannt, ob es nutzt so etwas wie: typeof(EqualityComparer<T>).GetInterface("IEqualityComparer<T>");
Irgendwelche Vorschläge ..
mit freundlicher Genehmigung von Reflektor:
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>();
}
So wie Sie sehen können, wenn T = string es wird zurückkehren GenericEqualityComparer<string>
.
Beat mich dazu: P –
Ich weiß nicht, ob das hilfreich ist. Es zeigt, welche nicht-öffentliche Klasse hinter der Szene verwendet wird, aber es gibt keine Informationen darüber, wie die nicht-öffentliche 'GenericEqualityComparer
EqualityComparer<T>.Default
Werke die virtual
Methoden Equals(object)
und GetHashCode()
Aufruf, die von System.Object
definiert sind, aber durch T
werden oder kann nicht außer Kraft gesetzt werden.
Beachten Sie, dass, da die Metoden virtual
sind, eine Implementierung einer abgeleiteten Klasse als T
verwendet werden kann. Zum Beispiel:
EqualityComparer<object>.Default
.Equals(new Uri("http://example.com/"), new Uri("http://example.com/"))
wird true
zurückkehren, auch wenn
Object.ReferenceEquals(new Uri("http://example.com/"), new Uri("http://example.com/"))
und
(object)new Uri("http://example.com/") == (object)new Uri("http://example.com/")
beide Rück false
.
In dem Fall, in dem T
string
ist, überlädt die Klasse System.String
die beiden fraglichen Methoden und verwendet einen ordinalen Vergleich. In diesem Fall sollte es also System.StringComparer.Ordinal
entsprechen. Und natürlich string
ist eine sealed
Klasse, so könnte keine andere Klasse von string
abgeleitet werden und Equals
und GetHashCode
auf eine seltsame Weise übersteuern.
Auch - Der Vorteil ist, dass zuerst überprüft, ob T implementiert IEquatable
Warum sollte 'GetInterface' gesagt werden, um das' System.Type'-Objekt für die Schnittstelle zu erhalten, die es selbst implementiert? Wie wäre das nützlich? Es könnte einfach 'typeof (IEqualityComparer)' sagen, wenn es diesen Typ somhow benötigt, aber das braucht es nicht. Es muss eine Instanz von EqualityComparer zurückgeben, die wir verwenden können. Da die Klasse "abstrakt" ist, muss eine Instanz einer nicht abstrakten abgeleiteten Klasse erstellt und zurückgegeben werden. Aber vielleicht fragen Sie wirklich, wie sich das zurückgegebene Objekt verhält? (Zumindest habe ich das unten beantwortet.) –