genericas - crear un objeto generico c#
¿Por qué C no admite tipos genéricos implícitos en los constructores de clases? (3)
¿Por qué C # no admite esta inferencia de tipo genérico de nivel de clase?
Porque generalmente son ambiguos. Por el contrario, la inferencia de tipo es trivial para llamadas a funciones (si todos los tipos aparecen en argumentos). Pero en el caso de llamadas de constructor (funciones glorificadas, por el bien de la discusión), el compilador tiene que resolver múltiples niveles al mismo tiempo. Un nivel es el nivel de clase y el otro es el nivel de argumentos del constructor. Creo que resolver esto es algorítmicamente no trivial. Intuitivamente, diría que es incluso NP completo.
Para ilustrar un caso extremo donde la resolución es imposible, imagine la siguiente clase y dígame qué debe hacer el compilador:
class Foo<T> {
public Foo<U>(U x) { }
}
var x = new Foo(1);
C # no requiere que especifique un parámetro de tipo genérico si el compilador puede inferirlo, por ejemplo:
List<int> myInts = new List<int> {0,1,1,
2,3,5,8,13,21,34,55,89,144,233,377,
610,987,1597,2584,4181,6765};
//this statement is clunky
List<string> myStrings = myInts.
Select<int,string>( i => i.ToString() ).
ToList<string>();
//the type is inferred from the lambda expression
//the compiler knows that it''s taking an int and
//returning a string
List<string> myStrings = myInts.
Select( i => i.ToString() ).
ToList();
Esto es necesario para los tipos anónimos en los que no se sabe cuál sería el parámetro de tipo (en intellisense aparece como ''a
) porque es agregado por el compilador.
Los parámetros de tipo de nivel de clase no te permiten hacer esto:
//sample generic class
public class GenericDemo<T>
{
public GenericDemo ( T value )
{
GenericTypedProperty = value;
}
public T GenericTypedProperty {get; set;}
}
//why can''t I do:
int anIntValue = 4181;
var item = new GenericDemo( anIntValue ); //type inference fails
//however I can create a wrapper like this:
public static GenericDemo<T> Create<T> ( T value )
{
return new GenericDemo<T> ( value );
}
//then this works - type inference on the method compiles
var item = Create( anIntValue );
¿Por qué C # no admite esta inferencia de tipo genérico de nivel de clase?
En realidad, tu pregunta no está mal. He estado jugando con un lenguaje de programación genérico en los últimos años y aunque nunca he llegado a desarrollarlo (y probablemente nunca lo haya hecho), he pensado mucho sobre la inferencia de tipo genérico y una de mis principales prioridades es siempre ha sido para permitir la construcción de clases sin tener que especificar el tipo genérico.
C # simplemente carece del conjunto de reglas para hacer esto posible. Creo que los desarrolladores nunca vieron la necesidad de incluir esto. En realidad, el siguiente código estaría muy cerca de tu proposición y resolvería el problema. Todas las necesidades de C # son un soporte de sintaxis agregado.
class Foo<T> {
public Foo(T x) { … }
}
// Notice: non-generic class overload. Possible in C#!
class Foo {
public static Foo<T> ctor<T>(T x) { return new Foo<T>(x); }
}
var x = Foo.ctor(42);
Como este código realmente funciona, hemos demostrado que el problema no es de semántica sino simplemente de falta de soporte. Creo que tengo que recuperar mi publicación anterior. ;-)
Gracias Konrad, esa es una buena respuesta (+1), pero solo para expandirla.
Supongamos que C # tiene una función de constructor explícita:
//your example
var x = new Foo( 1 );
//becomes
var x = Foo.ctor( 1 );
//your problem is valid because this would be
var x = Foo<T>.ctor<int>( 1 );
//and T can''t be inferred
Tienes razón en que el primer constructor no se puede inferir.
Ahora regresemos a la clase
class Foo<T>
{
//<T> can''t mean anything else in this context
public Foo(T x) { }
}
//this would now throw an exception unless the
//typeparam matches the parameter
var x = Foo<int>.ctor( 1 );
//so why wouldn''t this work?
var x = Foo.ctor( 1 );
Por supuesto, si vuelvo a agregar tu constructor (con su tipo alternativo) tenemos una llamada ambigua, exactamente como si una sobrecarga de método normal no pudiera resolverse.