1024programmer Asp.Net Generic learning

Generic learning

Learning about generics

generic learning

1. Introduction of generics

  1. Generics—General: broad–uncertain; type: type—uncertain type
  2. Everywhere
  3. When calling a normal method, the parameter type is determined when it is declared. Just pass the parameters according to the type
    a. If there are 100 types—100 methods? –very tired
    b. Is there a method that can meet different types of needs?

Traditional methods

 public static class CommonMethod
     {
         public static void ShowInt(int Parameter)
         {
             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
         }

         public static void ShowString(string Parameter)
         {
             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
         }

         public static void ShowDateTime(DateTime Parameter)
         {
             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
         }
     }
 
  1. Object type as parameter—-different parameters can be passed
    a. Any address appearing in a subclass can be replaced by the parent class
    b. Everything is an object—any type inherits from Object

Use Object type

 public static class CommonMethod
     {
         public static void ShowObject(object Parameter)
         {
             Console.WriteLine($"This is {typeof(CommonMethod).Name} parameter={Parameter},type={Parameter.GetType().Name} ");
         }
     }
 
  1. Question
    a. Performance issues —Boxing and unboxing—In C# syntax, the type is determined according to the declaration (stack, managed heap)
    b. Type safety issues

We use an example to illustrate the performance issue

public class PerformanceTest
     {
         public static void Show()
         {
             int ivalue = 1234;
             //time consumed
             long commonSecond = 0;
             long objectSecond = 0;
             long genericSecond = 0;

             {
                 Stopwatch sw = new Stopwatch();
                 sw.Start();
                 for (int i = 0; i < 1000_000_000; i++) {
                     ShowInt(ivalue);
                 }
                sw.Stop();
                 commonSecond = sw.ElapsedMilliseconds;
             }

             {
                 Stopwatch sw = new Stopwatch();
                 sw.Start();
                 for (int i = 0; i < 1000_000_000; i++)
                 {
                     ShowObject(ivalue);
                 }
                 sw.Stop();
                 objectSecond = sw.ElapsedMilliseconds;
             }

             {
                 Stopwatch sw = new Stopwatch();
                 sw.Start();
                 for (int i = 0; i < 1000_000_000; i++)
                 {
                     Show(ivalue);
                 }
                 sw.Stop();
                 genericSecond = sw.ElapsedMilliseconds;
             }
             Console.WriteLine($"commonSecond: {commonSecond} objectSecond: {objectSecond} genericSecond :{genericSecond} ");
         }


        


         private static void ShowInt(int r)
         {

         }

         private static void ShowObject(object o)
         {

         }


          private static void Show(T parameter)
         {

         }

     }
 

The result is:

  1. Is there a method that has good performance and can support multiple types? —Generic methods
    a. The declaration has an extra pair of angle brackets + placeholder T
    b. Calling — also requires an additional pair of angle brackets. The type specified in the angle brackets must be consistent with the type of the passed parameter.
    c. If the parameter can be pushed out of the type—the angle brackets can be omitted.
  2. Generic methods—achieve high performance—one method can meet the needs of different types:—let the horse run and let the horse eat grass

Second, generic declaration

1. Generic method: add a pair of angle brackets after the method name, with placeholders in the angle brackets
2. Delayed declaration: When declaring, just give a placeholder T. What type is T? I don’t know what type—when you call, you specify what you are, and when you call, it is what you say;
3. Placeholder: T —type parameter — type variable
4. When type parameters are used as parameters of a method, specify the parameter type.

3. Characteristics and principles of generics–How are they supported by the bottom layer?

  1. In high-level languages, the defined generic T must be a specific type when executed by the computer.
  2. How to support it at the bottom level? —As you can see at the bottom level, the generated result is LIST<c// b. You can only pass the ISports interface or the class that implements this interface.
    // c. You can add functions or obtain new functions.
    public static void ShowInterface(T tValue) where T : ISports
    {
    tValue.run();
    }

    //Reference type constraints
    // a. You can only pass the type in
    public static void ShowClass(T tValue) where T : class
    {

    }

    //Value type constraints
    // a. Only value types can be passed in
    public static void ShowValue(T tValue) where T : struct
    {

    }

    //No parameter constructor constraints
    //
    public static void ShowNew(T tValue) where T : new()
    {
    T t= new T();
    }

    //enumeration constraints
    public static void ShowEnum(T tValue) where T : Enum
    {

    }

    Seven. Generic cache—generic class

    Generic cache can generate a new copy of a class based on different types; generate countless copies;

     public class GenericCacheTest
         {
             public static void Show()
             {
    
                 //Normal cache
                 {
                     for (int i = 0; i < 5; i++)
                     {
                         Console.WriteLine(DictionaryCache.GetCache()); //GenericCacheInt
                         Thread.Sleep(10);
                         Console.WriteLine(DictionaryCache.GetCache());// GenericCachelong
                         Thread.Sleep(10);
                         Console.WriteLine(DictionaryCache.GetCache());
                         Thread.Sleep(10);
                         Console.WriteLine(DictionaryCache.GetCache());
                         Thread.Sleep(10);
                         Console.WriteLine(DictionaryCache.GetCache());
                         Thread.Sleep(10);
                     }
                 }
    
                 //generic cache
                 {
                     for (int i = 0; i < 5; i++)
                     {
                         Console.WriteLine(GenericCache.GetCache()); //GenericCacheInt
                         Thread.Sleep(10);
                         Console.WriteLine(GenericCache.GetCache());// GenericCachelong
                         Thread.Sleep(10);
                         Console.WriteLine(GenericCache.GetCache());
                         Thread.Sleep(10);
                         Console.WriteLine(GenericCache.GetCache());
                         Thread.Sleep(10);
                         Console.WriteLine(GenericCache.GetCache());
                         Thread.Sleep(10);
                     }
                 }
             }
         }
    
         /// 
         /// Dictionary cache: static attributes are resident in memory
         /// 
         public class DictionaryCache
         {
             private static Dictionary _TypeTimeDictionary = null;
    
             //The static constructor is executed only once in the entire process;
             static DictionaryCache()
             {
                 Console.WriteLine("This is DictionaryCache static constructor");
                 _TypeTimeDictionary = new Dictionary();
             }
             public static string GetCache()
             {
                 Type type = typeof(T);
                 if (!_TypeTimeDictionary.ContainsKey(type))
                 {
                     _TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
                 }
                 return _TypeTimeDictionary[type];
             }
         }
    
    
         /// 
         ///Generic cache:
         /// 
         /// 
         public class GenericCache
         {
             static GenericCache()
             {
                 Console.WriteLine("This is GenericCache static constructor");
                 //_TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
                 _TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
             }
    
             private static string _TypeTime = "";
    
             public static string GetCache()
             {
                 return _TypeTime;
             }
    
         }
     

    Seven, covariance and contravariance of generics

    For example, we have an animal class and its subclass cat class

     public class Animal
         {
             public int Id { get; set; }
    
         }
    
         public class Cat : Animal {
             public string Name { get; set; }
         }
     

    We can use code like this

    //Any subclass can be declared using the parent class
     Animal animal1 = new Cat();
     //It is not necessarily possible to use subclasses to declare parent classes
     Cat cat2 = new Animal();
    
     

    We will encounter this problem again
    A cat is a bunch of animals
    A bunch of cats is not a bunch of animals—speaking from a colloquial point of view, it is a bit inconsistent with human logic.

    List animals = new List();
     //Report error
     List animals2 = new List();
     

    Why? —The second category has no parent-child relationship; of course it cannot be replaced; this is determined by C# syntax.
    Generics are unfriendly and uncoordinated;

    This introduces our covariance and contravariance;
    Covariance and contravariance only apply to generic interfaces and generic delegates

    //Covariance allows the right side to use subclasses and the left side to use parent classes
     //out: Modify type parameters: you can use subclasses on the right side and parent classes on the left side.
     IEnumerable animals1=new List();
     IEnumerable animals3= new List();
     

    Covariance: Out type parameters can only be used as return values, not parameters

    Contravariant In can only be used as a parameter and cannot be used as a return value

     public interface ICustomerListIn
         {
             void show(T t);
         }
    
         public class CustomerListIn:ICustomerListIn
         {
             public void show(T t)
             {
    
             }
         }
     

    Inverse code example

    //Inverse variation: You can use the parent class on the right side and the subclass on the left side;
     ICustomerListIn customerListIn = new CustomerListIn();
     ICustomerListIn customerListIn1 = new CustomerListIn();
     

    Why are there covariance and contravariance?
    What would happen if there were no covariance and contravariance?

    
      public interface ICustomerList {
             T Get();
    
             void show(T t);
         }
    
         public class CustomerList:ICustomerList
         {
             public T Get()
             {
                 return default(T);
             }
             public void show(T t)
             {
    
             }
         }
    
     }
    
     ICustomerList customerList=new CustomerList();
     ICustomerList customerList1 = new CustomerList();
    
     

    Covariance and contravariance of generics are like advanced constraints, designed to avoid

    1. Use the subclass as a parameter, but pass the parent class as a parameter;
    2. The subclass is used as the return value, but when returning, a parent class is returned.

    lt;Animal> animals2 = new List();

    Why? —The second category has no parent-child relationship; of course it cannot be replaced; this is determined by C# syntax.
    Generics are unfriendly and uncoordinated;

    This introduces our covariance and contravariance;
    Covariance and contravariance only apply to generic interfaces and generic delegates

    //Covariance allows the right side to use subclasses and the left side to use parent classes
     //out: Modify type parameters: you can use subclasses on the right side and parent classes on the left side.
     IEnumerable animals1=new List();
     IEnumerable animals3= new List();
     

    Covariance: Out type parameters can only be used as return values, not parameters

    Contravariant In can only be used as a parameter and cannot be used as a return value

     public interface ICustomerListIn
         {
             void show(T t);
         }
    
         public class CustomerListIn:ICustomerListIn
         {
             public void show(T t)
             {
    
             }
         }
     

    Inverse code example

    //Inverse variation: You can use the parent class on the right side and the subclass on the left side;
     ICustomerListIn customerListIn = new CustomerListIn();
     ICustomerListIn customerListIn1 = new CustomerListIn();
     

    Why are there covariance and contravariance?
    What would happen if there were no covariance and contravariance?

    
      public interface ICustomerList {
             T Get();
    
             void show(T t);
         }
    
         public class CustomerList:ICustomerList
         {
             public T Get()
             {
                 return default(T);
             }
             public void show(T t)
             {
    
             }
         }
    
     }
    
     ICustomerList customerList=new CustomerList();
     ICustomerList customerList1 = new CustomerList();
    
     

    Covariance and contravariance of generics are like advanced constraints, designed to avoid

    1. Use the subclass as a parameter, but pass the parent class as a parameter;
    2. The subclass is used as the return value, but when returning, a parent class is returned.
This article is from the internet and does not represent1024programmerPosition, please indicate the source when reprinting:https://www.1024programmer.com/generic-learning-2/

author: admin

Previous article
Next article

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

Contact us

181-3619-1160

Online consultation: QQ交谈

E-mail: [email protected]

Working hours: Monday to Friday, 9:00-17:30, holidays off

Follow wechat
Scan wechat and follow us

Scan wechat and follow us

Follow Weibo
Back to top
首页
微信
电话
搜索