Express C # argomenti generici di tipo più sincero?
-
11-12-2019 - |
Domanda
ispirato a
Confrontando due collezioni per l'uguaglianza indipendentemente dall'ordine degli articoli in esse
.Ho creato un metodo di estensione per verificare se due raccolte sono equivalenti.Per utilizzare il metodo di estensione, devo specificare due parametri di tipo come questo:
IsEquivalentToTestHelper<ObservableCollection<string>, string>(first, second, true);
.
C'è un modo per implementare il metodo di estensione in modo che sia necessario specificare solo un vincolo generico (E.G. ObservableCollection<string>
)?
Aggiornamento : ha pubblicato il codice modificato in base alle risposte come risposta aggiuntiva alla domandaQuesto ha ispirato questo.
Ecco il mio codice originale:
.static public class EnumerableExtensions
{
static public bool IsEquivalentTo<E,T>(this E first, E second) where E : IEnumerable<T>
{
if ((first == null) != (second == null))
return false;
if (!object.ReferenceEquals(first, second) && (first != null))
{
if (first.Count() != second.Count())
return false;
if ((first.Count() != 0) && HaveMismatchedElement<E,T>(first, second))
return false;
}
return true;
}
private static bool HaveMismatchedElement<E,T>(E first, E second) where E : IEnumerable<T>
{
int firstCount;
int secondCount;
var firstElementCounts = GetElementCounts<E,T>(first, out firstCount);
var secondElementCounts = GetElementCounts<E,T>(second, out secondCount);
if (firstCount != secondCount)
return true;
foreach (var kvp in firstElementCounts)
{
firstCount = kvp.Value;
secondElementCounts.TryGetValue(kvp.Key, out secondCount);
if (firstCount != secondCount)
return true;
}
return false;
}
private static Dictionary<T, int> GetElementCounts<E,T>(E enumerable, out int nullCount) where E : IEnumerable<T>
{
var dictionary = new Dictionary<T, int>();
nullCount = 0;
foreach (T element in enumerable)
{
if (element == null)
{
nullCount++;
}
else
{
int num;
dictionary.TryGetValue(element, out num);
num++;
dictionary[element] = num;
}
}
return dictionary;
}
static private int GetHashCode<E,T>(IEnumerable<T> enumerable) where E : IEnumerable<T>
{
int hash = 17;
foreach (T val in enumerable.OrderBy(x => x))
hash = hash * 23 + val.GetHashCode();
return hash;
}
}
Soluzione
static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second)
. Altri suggerimenti
Potresti far cadere il primo e mantenere il secondo:
static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second)
. Hai solo bisogno di sostituire ogni E
con IEnumerable<T>
e rilasciare le istruzioni "
Ad esempio:
static public bool IsEquivalentTo<T>(this IEnumerable<T> first, IEnumerable<T> second)
var firstElementCounts = GetElementCounts<IEnumerable<T>,T>(first, out firstCount);
static private int GetHashCode<T>(IEnumerable<T> enumerable)
.