1: ¿Qué es el uso genérico y genérico más la contravarianza covariante?

1. ¿Qué es genérico?

就在在声明的时候,带上一个<>,指定类型参数,调用的时候指定类型调用---泛型;

concepto

Concepto que se puede omitir directamente.

  1. Método genérico: un método satisface diferentes tipos de necesidades;

  2. Clase genérica: una clase satisface las necesidades de diferentes clases;

  3. Interfaz genérica: una interfaz satisface las necesidades de diferentes interfaces;

  4. Delegación genérica: una delegación satisface las necesidades de diferentes delegaciones;

    El objeto es la clase principal de todos los tipos.
    Cualquier lugar donde aparezca una clase principal se puede reemplazar por una subclase.

Por ejemplo

下面代码段,这就是常用的泛型<>;就是说在传类型以前他可以是任何类型。传int或类等类或结构类型的时候就限定了他的类型。
List<int> intlist = new List<int>();
List<string> stringlist = new List<string>();

2. ¿Cómo declarar y utilizar genéricos?

Ejemplo de código y efecto

public class Monitor
    {
    
    
        public static void Show()
        {
    
    
            Show<int>(1);
        }
        private static void Show<T>(T tParameter)
        {
    
    
            Console.WriteLine($"调用第一次泛型{tParameter}");
        }
    }

Diagrama de ejecución de código

3. ¿Pensamiento genérico con retraso?

Trata de ser lo más específico posible

Al escribir código, coloque el contenido de implementación real lo más atrás posible. Un programa tan confuso nos da muchas posibilidades. Por ejemplo, podemos acordar qué parámetro debería ser cuando llamamos.

4. ¿Los beneficios y principios de los genéricos?

beneficio

  1. Un método puede satisfacer diferentes tipos de necesidades. (En una clase, debe pasar parámetros, como int, string, etc., y no puede escribir un nuevo método para cada tipo diferente de parámetro. Si no puede lograr una alta disponibilidad y escalabilidad, puede usar genéricos. Por supuesto, Object también se puede usar aquí, pero La velocidad será hasta dos veces más lenta, ya que implica boxear y unboxing)
    Boxing es convertir "tipo de valor" en "tipo de referencia" (Objeto);
    unboxing es convertir "tipo de referencia" en "tipo de valor";
  2. Alto rendimiento (su velocidad es la misma que cuando se usa int, string y otras estructuras o clases directamente).

Principios y conceptos

Después genéricos se compilan, parámetros genéricos se generan marcadores de posición. 2
métodos ordinarios Finalmente, diferentes serán generadas de acuerdo con la llamada;
genéricos se han lanzado en .NetFramework2;
genéricos no son un azúcar sintáctico (azúcar sintáctica se refiere a la adición de una cierta sintaxis, derecha La función del lenguaje no tiene ningún efecto, lo que es conveniente para que lo utilicen los programadores)
Genéricos: actualización del compilador + actualización de CLR Los
genéricos son compatibles con la actualización del marco;

5. ¿Clases genéricas, métodos, interfaces, delegados?

concepto

  1. Método genérico: un método satisface diferentes tipos de necesidades;
  2. Clase genérica: una clase satisface las necesidades de diferentes clases;
  3. Interfaz genérica: una interfaz satisface las necesidades de diferentes interfaces;
  4. Delegación genérica: una delegación satisface las necesidades de diferentes delegaciones;

6. Restricciones genéricas, almacenamiento en caché genérico?

Qué restricciones resuelven

Cuando se procesan los parámetros entrantes, es posible que el tipo real no coincida.

Clasificación de restricciones genéricas

  1. Restricción de clase base: Restrinja este T para que sea Personas; la restricción solo puede pasar Personas o subclases de Personas
  2. Restricción de interfaz: La restricción de esta T es que la clase de implementación de la interfaz ISports puede llamar al método en la interfaz, correcto; al llamar, solo se puede pasar a la clase que implementa esta interfaz, obligación
  3. Restricciones de tipo de referencia: solo se pueden pasar parámetros de tipo de referencia
  4. Restricciones de tipo de valor: solo se pueden pasar parámetros de tipo de valor
  5. Restricciones en constructores sin parámetros: los parámetros pasados ​​deben tener un constructor sin parámetros y solo necesitan escribir en el tipo calificado: new ()

Cómo escribir restricciones

Observando el siguiente segmento de código. Solo es necesario agregar
donde T (tipo de parámetro) después del parámetro: (tipo calificado) El
tipo calificado puede ser

		/// <summary>
        /// 值类型约束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static T ShowStruct<T>(T tParameter)
          where T : struct
        {
    
    
            return default(T);  //任何类型都可以,default(T) 根据实际的调用类来生成默认值;
        }
         
        /// <summary>
        ///引用类型约束
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static T ShowClass<T>(T tParameter)
          where T : class
        {
    
    
            return default(T);  //任何类型都可以,default(T) 根据实际的调用类来生成默认值;
        }

restricción

Escenarios de aplicaciones de almacenamiento en caché

举例子:比如要进行根据实体类获取增删改查语句。这时候就可以用到缓存放起来。
/// <summary>
    /// 字典缓存:静态属性常驻内存
    /// </summary>
    public class DictionaryCache
    {
    
    
        private static Dictionary<Type, string> _TypeTimeDictionary = null;
        static DictionaryCache()
        {
    
    
            Console.WriteLine("This is DictionaryCache 静态构造函数");
            _TypeTimeDictionary = new Dictionary<Type, string>();
        }
        public static string GetCache<T>()
        {
    
    
            Type type = typeof(T);
            if (!_TypeTimeDictionary.ContainsKey(type))
            {
    
    
                //_TypeTimeDictionary[type] = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));  
                _TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
            }
            return _TypeTimeDictionary[type];
        }
    }

7. ¿Contravarianza covariante?

concepto

Covarianza: Out solo se puede usar como valor de retorno, no como parámetro, y el lado derecho se puede usar como subclase.
Inverter: in solo se puede usar como parámetro, no como valor de retorno, y el lado derecho se puede usar como clase principal

utilizar

El siguiente bloque de código generará un error, porque especificamos el tipo genérico como Animal, y se producirá un error cuando se pase Cat como instancia.
Nota: el gato se hereda de los animales

	
    #region 协变  逆变例子
    /// <summary>
    /// T 就只能做参数  不能做返回值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ICustomerListIn<in T>
    {
    
    
       //T Get();
        void Show(T t);
    }

    public class CustomerListIn<T> : ICustomerListIn<T>
    {
    
    
        //public T Get()
        //{
    
    
        //    return default(T);
        //}
        public void Show(T t)
        {
    
    

        }
    }

    /// <summary>
    /// out 协变 只能是返回结果 
    /// 泛型T 就只能做返回值; 不能做参数; 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface ICustomerListOut<out T>
    {
    
    
        T Get();
       //void Show(T t); 
    }

    public class CustomerListOut<T> : ICustomerListOut<T>
    {
    
    
        public T Get()
        {
    
    
            return default(T);
        }

        //public void Show(T t)
        //{
    
    

        //}
    }

    public interface IMyList<in inT, out outT>
    {
    
    
        void Show(inT t);
        outT Get();
        outT Do(inT t);

        out 只能是返回值   in只能是参数
        //void Show1(outT t);//左边声明是父类---右边实例化是子类 new MyList<Cat, Cat>()---outT是cat--方法调用时以左边为准,传递的是animal的子类-狗
        //inT Get1(); 
    }

    /// <summary>
    /// out 协变 只能是返回结果 
    /// in  逆变 只能是参数
    /// 
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>

    public class MyList<T1, T2> : IMyList<T1, T2>
    {
    
    
        public void Show(T1 t)
        {
    
    
            Console.WriteLine(t.GetType().Name);
        }

        public T2 Get()
        {
    
    
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }

        public T2 Do(T1 t)
        {
    
    
            Console.WriteLine(t.GetType().Name);
            Console.WriteLine(typeof(T2).Name);
            return default(T2);
        }
    }
    #endregion

8. ¿Una ganancia inesperada?

recompensa

Jajajaja, aprendí una nueva forma de deletrear cuerdas.
Agregue $ al frente de la cadena de empalme, qué parámetros deben agregarse en el medio, escriba {} y coloque los parámetros en él.

Console.WriteLine($"调用第一次泛型{tParameter}");

Supongo que te gusta

Origin blog.csdn.net/hello_mr_anan/article/details/107444182
Recomendado
Clasificación