2010-04-25 5 views
5

Considere la siguiente declaración de una clase de utilidad genérica en Delphi 2010:¿Por qué Delphi no puede inferir el tipo para un parámetro TEnumerable <T>?

TEnumerableUtils = class 
public 
    class function InferenceTest<T>(Param: T): T; 
    class function Count<T>(Enumerable: TEnumerable<T>): Integer; overload; 
    class function Count<T>(Enumerable: TEnumerable<T>; Filter: TPredicate<T>): Integer; overload; 
end; 

De alguna manera el tipo compilador de inferencia parece tener problemas aquí: trabaja

var 
    I: Integer; 
    L: TList<Integer>; 
begin 
    TEnumerableUtils.InferenceTest(I); // no problem here 
    TEnumerableUtils.Count(L);   // does not compile: E2250 There is no overloaded version of 'Count' that can be called with these arguments 
    TEnumerableUtils.Count<Integer>(L); // compiles fine 
end; 

La primera llamada como se esperaba y T es correcta inferido como entero.

La segunda llamada no funciona, a menos que también agregue <Integer> - entonces funciona, como se puede ver en la tercera llamada. ¿Estoy haciendo algo mal o la inferencia tipo en Delphi simplemente no es compatible con esto (no creo que sea un problema en Java, por lo que esperaba que funcionara en Delphi también).

Respuesta

9

El compilador necesitaría hacer la coincidencia de patrones para inferir tipos de parámetros; actualmente no lo hace. El compilador está limitado a una inferencia bastante simple: si el tipo de parámetro es de tipo tipo de parámetro, entonces el compilador puede resolverlo, pero no mucho más allá de eso.

El tipo de argumento en su ejemplo no es un parámetro de tipo simple, sino que es más bien un tipo genérico construido (está construido con el parámetro de tipo T del método, pero está construido de todos modos). El compilador necesita hacer dos inferencias para descubrir el valor de T. Primero, necesita ver que el tipo genérico del tipo construido es un antepasado del tipo genérico TList<T>; y también debe coincidir con el parámetro de tipo T en la lista de parámetros de tipo del tipo construido con el tipo concreto Integer en el antecesor TList<T>.

+1

En ese caso, sería demasiado duro decir que la implementación de la inferencia tipo Delphi es apenas lo suficientemente buena para garantizar su inclusión en la caja como una "nueva característica", pero no lo suficientemente buena para ser considerada de manera significativa " completar "? – Deltics

+1

A veces "solo lo suficientemente bueno" realmente no es lo suficientemente bueno en absoluto, mejor no tener algo que tener algo que no puede cuajar, que no se agita y que apenas puede nadar, pero que, sin embargo, da vueltas llamándose a sí mismo un "pato". "Mejor" en el sentido de que no conduciría a este tipo de pregunta/confusión que llama la atención sobre la "brecha de características" y que da munición a aquellos que intentan despedir a Delphi como un "ha sido/funcionó". Es mejor decir: "la inferencia de tipo no se sienta cómodamente con la naturaleza de Pascal", que es, en mi humilde opinión, una posición perfectamente verdadera y válida. – Deltics

+0

Gracias, Barry. Parece que tengo que vivir con eso entonces. Tal vez el próximo año ... ;-) Una pequeña pregunta relacionada si pudiera: ¿debería basar esta clase utils en IEnumerable en vez de TEnumerable? Parece ser más general para mí, y la ayuda indica que IEnumerable no tiene que declararse en las clases que tienen un método GetEnumerator. –

Cuestiones relacionadas