1. Genérico
1.1 Introducción de genéricos: declaración diferida
Cuando se declara un método genérico, el tipo no se escribe y el tipo se especifica cuando se llama.
Declaración de aplazamiento: posponer todo puede posponerse.
1.2 Cómo declarar y usar genéricos
Método genérico: agregue corchetes angulares después del nombre del método, que contiene parámetros de tipo
El parámetro de tipo es en realidad una declaración de tipo T, el método puede usar este tipo T.
Como se muestra a continuación:
público estático vacío Show <T> (T t)
{
Console.WriteLine ($ "Esto es {typeof (CustomMethod)}, paramater = {t.GetType (). Name}, value = {t}");
}
1.3 Beneficios y principios de los genéricos
El rendimiento de los métodos genéricos es el mismo que el de los métodos ordinarios. Cuando un método es declarado por un genérico, el tipo no se escribe. Qué tipo de T es. Solo cuando se llama, sabe que un método puede cumplir con diferentes tipos.
1.4 Clase genérica, método genérico, interfaz genérica, delegado genérico
1.4.1 Tipos genéricos
Una clase satisface diferentes tipos de necesidades.
Los detalles son los siguientes:
Clase pública BaseModel
{
public int Id {get; conjunto; }
}
clase pública GenericClass <T>
donde T: BaseModel // es una restricción de clase base genérica
{
}
1.4.2 Métodos genéricos
Una forma de satisfacer diferentes tipos de necesidades.
Los detalles son los siguientes:
público estático vacío Show <T> (T t)
{
Console.WriteLine ($ "Esto es {typeof (CustomMethod)}, paramater = {t.GetType (). Name}, value = {t}");
}
1.4.3 Interfaz genérica
Una interfaz satisface diferentes tipos de necesidades.
// interfaz genérica
interfaz pública IGenericInterface <T>
{
vacío público SayHi (T t);
}
1.4.4 Delegación genérica
Un delegado satisface diferentes tipos de necesidades.
delegado público nulo Do <T> (T t);
1.5 Restricciones genéricas
Sin restricciones, los genéricos serán muy limitados. Hay 5 tipos de restricciones genéricas. Como sigue:
1.5.1 Restricciones de clase base
Donde T: BaseModel
BaseModel se puede usar como clase base
Solo los objetos de este tipo u objetos derivados de este tipo pueden usarse como parámetros de tipo. (Las restricciones de sellado no son aceptables porque no tienen sentido).
// Clase base
Clase pública BaseModel
{
public int Id {get; conjunto; }
}
// clase genérica
clase pública GenericClass <T>
donde T: BaseModel // es una restricción de clase base genérica
{
}
Llamada:
GenericConstraint.Show <BeiJing> (new BeiJing ());
1.5.2 Restricciones de tipo de referencia
// Restricciones de tipo de referencia
public static T Obtenga <T> () donde T: clase
{
return default (T); // default es una palabra clave, de acuerdo con el tipo T devuelve el valor predeterminado correspondiente
}
Llamada:
GenericConstraint.Get <Person> (new Person ());
1.5.3 Restricciones de tipo de valor
// Restricciones de tipo de valor
Público estático D GetD <D> () donde D: struct
{
retorno por defecto (D);
}
Llamada:
GenericConstraint.GetD <int> (116);
1.5.4 Constructor sin argumentos
// Sin restricción de constructor de parámetros
Público estático S GetS <S> ()
donde S: new () // Restricción de constructor sin comidas
{
volver nuevo S ();
}
Llamada:
GenericConstraint.GetS <Chinese> ();
1.5.5 Restricciones de interfaz
// Restricciones de interfaz
público estático vacío Show2 <T> (T t) donde T: ISports
{
t.Baloncesto ();
}
Llamada:
GenericConstraint.Show2 <USA> (new USA ());
1.6 Covarianza e inversión
Las llamadas covarianza e inversión están relacionadas con los genéricos (utilizados principalmente en interfaces).
1.6.1 Covarianza
Decora el valor de retorno
Deje que el lado derecho use subclases, lo que facilita el uso de genéricos (subclases a clases para padres)
Fuera de la modificación, después de la covariación solo puede devolver resultados, no parámetros
IEnumerable <Bird> birdList = new List <Sparrow> ();
// fuera covariante, solo puede devolver resultados (subclase a clase primaria)
interfaz pública ICustomerListOut <out T>
{
T Get ();
}
clase pública CustomerListOut <T>: ICustomerListOut <T>
{
public T Get ()
{
retorno por defecto (T);
}
}
ICustomerListOut <Bird> list2 = new CustomerListOut <Sparrow> ();
Func <Bird> func = new Func <Sparrow> (() => nulo);
IEnumerable <Bird> list3 = new List <Sparrow> ();
1.6.2 Inversor
Modificar parámetros entrantes
Haga que la clase principal esté disponible a la derecha, lo que facilita el uso de genéricos (la clase de rotor principal)
En modificado, solo se puede usar como parámetro después de la inversión
// en Inverter solo puede ser parámetro de entrada (tipo de rotor principal)
interfaz pública ICustomerListIn <en T>
{
Show nulo (T t);
}
public class CustomerListIn <T>: ICustomerListIn <T>
{
Show público vacío (T t)
{
Console.WriteLine (t.GetType (). Name);
}
}
// inversor
ICustomerListIn <Sparrow> list1 = new CustomerListIn <Bird> ();
Acción <Sparrow> acción = nueva Acción <Bird> ((i) => {});
interfaz pública IMyList <inT, out outT>
{
Show nulo (inT t);
OUTT Get ();
outT Do (inT t);
}
clase pública MyList <T, T1>: IMyList <T, T1>
{
Show público vacío (T t)
{
Console.WriteLine (t.GetType (). Name);
}
public T1 Get ()
{
Console.WriteLine (typeof (T1) .Name);
retorno por defecto (T1);
}
público T1 Do (T t)
{
Console.WriteLine (t.GetType (). Name);
Console.WriteLine (typeof (T1) .Name);
retorno por defecto (T1);
}
}
IMyList <Sparrow, Bird> myList1 = new MyList <Sparrow, Bird> ();
IMyList <Sparrow, Bird> myList2 = new MyList <Sparrow, Sparrow> (); // 协 变
IMyList <Sparrow, Bird> myList3 = new MyList <Bird, Bird> (); // 逆变
IMyList <Sparrow, Bird> myList4 = new MyList <Bird, Sparrow> (); // 逆变 + 协 变
1.7 Caché genérico
Caché genérico, cada tipo generará una copia diferente (adecuada para diferentes tipos de escenarios que necesitan almacenar en caché un dato)
clase pública GenericCache <T>
{
cadena estática privada _TypeTime = "";
GenericCache estático ()
{
Console.WriteLine ("Este es el constructor estático GenericCache");
_TypeTime = $ "{typeof (T) .FullName} _ {DateTime.Now.ToString (" aaaa-MM-dd HH: mm: ss ")}";
}
cadena estática pública GetCache ()
{
return _TypeTime;
}
}
/// <resumen>
/// Caché de diccionario: los atributos estáticos residen en la memoria
/// </summary>
clase pública DictionaryCache
{
Diccionario estático privado <Tipo, cadena> _TypeTimeDictionary = null;
static DictionaryCache ()
{
Console.WriteLine ("Este es el constructor estático DictionaryCache");
_TypeTimeDictionary = new Dictionary <Type, string> ();
}
cadena estática pública GetCache <T> ()
{
Tipo type = typeof (Type);
if (! _TypeTimeDictionary.ContainsKey (tipo))
_TypeTimeDictionary [type] = $ "{typeof (T) .FullName} _ {DateTime.Now.ToString (" aaaa-MM-dd HH mm: ss ")}";
return _TypeTimeDictionary [tipo];
}
}