Considera T = stringa.In che modo EqualityComparer <T> .Default funziona internamente?
Sono curioso di sapere se si utilizza qualcosa come: typeof(EqualityComparer<T>).GetInterface("IEqualityComparer<T>");
Qualche suggerimento ..
Considera T = stringa.In che modo EqualityComparer <T> .Default funziona internamente?
Sono curioso di sapere se si utilizza qualcosa come: typeof(EqualityComparer<T>).GetInterface("IEqualityComparer<T>");
Qualche suggerimento ..
Per gentile concessione di riflettore:
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>();
}
Quindi, come si può vedere se T = stringa tornerà GenericEqualityComparer<string>
.
Mi picchia: P –
Non so se questo è utile. Mostra quale classe non pubblica viene utilizzata dietro la scena, ma non fornisce informazioni su come funziona la classe 'GenericEqualityComparer
EqualityComparer<T>.Default
opere chiamando i metodi virtual
Equals(object)
e GetHashCode()
che sono definiti da System.Object
ma può o non può essere sovrascritto dalle T
.
Si noti che poiché i metodi sono virtual
, è possibile utilizzare un'implementazione di una classe più derivata di T
. Ad esempio:
EqualityComparer<object>.Default
.Equals(new Uri("http://example.com/"), new Uri("http://example.com/"))
tornerà true
, anche se
Object.ReferenceEquals(new Uri("http://example.com/"), new Uri("http://example.com/"))
e
(object)new Uri("http://example.com/") == (object)new Uri("http://example.com/")
entrambi restituiscono false
.
Nel caso in cui T
è string
, classe System.String
sovraccarica i due metodi in questione e utilizzare un confronto ordinale. Quindi in questo caso dovrebbe essere equivalente a System.StringComparer.Ordinal
. E ovviamente string
è una classe sealed
, quindi nessun'altra classe potrebbe derivare da string
e sostituire Equals
e GetHashCode
in qualche modo strano.
Inoltre: il vantaggio è che verifica innanzitutto se T implementa 'IEquatable
Perché dire 'GetInterface' per ottenere l'oggetto' System.Type' per l'interfaccia che implementa da solo? Come sarebbe utile? Potrebbe semplicemente dire 'typeof (IEqualityComparer)' se fosse necessario digitare quel tipo, ma non è necessario. È necessario restituire un'istanza di 'EqualityComparer ' che possiamo usare. Poiché la classe è 'abstract', ciò comporta la creazione di un'istanza di una classe derivante non astratta e la sua restituzione. Ma forse chiedi veramente a cosa si comporta l'oggetto restituito? (Almeno era quello che ho risposto di seguito.) –