considerare le seguenti due metodi di estensione:Perché il compilatore sceglie di eseguire l'override con IEnumerable su IEnumerable <T>?
using System;
using System.Collections.Generic;
using System.Linq;
public static class Extensions
{
public static bool Contains(this IEnumerable self, object obj)
{
foreach (object o in self)
{
if (Object.Equals(o, obj))
{
return true;
}
}
return false;
}
public static bool ContainsEither<T>(this IEnumerable<T> self, T arg1, T arg2)
{
return self.Contains(arg1) || self.Contains(arg2);
}
}
Quando ho scritto il mio secondo metodo, intendevo per chiamare il metodo generico LINQ Enumerable.Contains<T>
(argomenti di tipo desunti dall'uso). Tuttavia, ho scoperto che in realtà è chiamando il primo metodo (mia abitudine Contains()
metodo di estensione. Quando io commento il mio metodo Contains()
, il secondo metodo compila bene, utilizzando il metodo Enumerable.Contains<T>()
.
La mia domanda è, perché il compilatore scegliere il mio metodo Contains()
con IEnumerable
argomento non generico su Enumerable.Contains<T>()
con IEnumerable<T>
argomento mi aspetterei che scegliere Enumerable.Contains<T>()
perché IEnumerable<T>
è più derivato di IEnumerable
Update:?.. Grazie a Jon Skeet per la grande risposta sarebbe interessante sapere perché i designer hanno scelto questo modo. Ho passato un po 'di tempo ad esplorare il caso s dove questo sarebbe un problema, ho pensato a uno (concesso un po 'di una portata)
public static double Average(this IEnumerable self)
{
double sum = 0;
long count = 0;
foreach (object obj in self)
{
sum += Convert.ToDouble(obj);
nItems++;
}
return sum/count;
}
object[] junk = new object[] { "9000", (byte)99, -8.555, 3154254325345UL };
double[] clean = new double[] { 9000, 99, -8.555, 3154254325345 };
double junkAvg = junk.Average();
double cleanAvg = clean.Average(); // compiler is choosing your Average() method where you'd prefer it to choose Enumerable.Average(IEnumerable<double>)
generici sono più specifici. –
In generale, in situazioni come questa, la domanda "perché" è generalmente interessante, ma probabilmente più importante è la domanda "come posso renderlo non .....". –
@ LasseV.Karlsen Davvero circa il perché. Potrei aver scritto Enumerable.Contains (...) o Contains (...) –