Perché non consentire l'implementazione dell'interfaccia sul posto in .NET?
Domanda
O mi manca qualcosa o .NET non supporta ciò che fa Java. Vorrei poter evitare di creare una piccola classe solo per implementare una piccola interfaccia. Ad esempio, il metodo di Linq si aspetta IEqualityComparer
. Quindi ho dovuto scrivere una piccola classe che implementa l'interfaccia. Tuttavia in Java posso semplicemente fare un new IEqualityComparer() { //interface declarations }
e sii fatto con esso. Allora, qual'è il problema?
Questo è in qualche modo correlato a questo post:
Una classe C# Anonymous può implementare un'interfaccia?.
Aggiunta: al momento ho aggiunto sovrascrivi Equals
e GetHashCode
.
Soluzione
Hai ragione, C# A differenza di Java, non supporta la nozione di classi interne anonime che possono implementare interfacce. Ho riscontrato lo stesso identico problema con IEqualityComparer
e alla fine è arrivato alla seguente soluzione.
public static class Utils {
private sealed class EqualityComparer<T> : IEqualityComparer<T> {
private readonly Func<T, T, bool> m_equals;
private readonly Func<T, int> m_getHashCode;
internal EqualityComparer(
Func<T, T, bool> equals,
Func<T, int> getHashCode) {
m_equals = equals;
m_getHashCode = getHashCode;
}
public bool Equals(T left, T right) {
return m_equals(left, right);
}
public int GetHashCode(T value) {
return m_getHasheCode(value);
}
}
public static IEqualityComparer<T> CreateEqualityComparer<T>(
Func<T, T, bool> equals,
Func<T, int> getHashCode) {
return new EqualityComparer<T>(equals, getHashCode);
}
}
Ora in luoghi in cui voglio un fly IEqualityComparer<T>
Posso solo fare quanto segue
var comparer = Utils.CreateEqualityComparer<Student>(
(left, right) => left.Name == right.Name,
value => value.Name.GetHashCode());
Altri suggerimenti
La risposta breve è che questo non è supportato in C #NET
Devo ammettere che sembra abbastanza pulito, ma normalmente non è davvero necessario. I metodi di confronto in LINQ sembrano essere l'eccezione, la maggior parte degli altri metodi LINQ accetta sovraccarichi che eseguono la stessa cosa usando i delegati, che possono essere implementati "sul posto" tramite espressioni Lambda.
Per questo esempio specifico ci sono una dispersione di post sul blog che hanno un'implementazione per a LambdaComparer
(o simile) che ti consente di fare proprio questo, anche se usando una sintassi un po 'meno elegante. Vedere Passare un'espressione Lambda al posto di ICOMparer o IEqualityComparer o qualsiasi interfaccia a metodo singolo? per un esempio.