C#Knowledge Compilation-Generics

 

1. Concepts

Generic is a new grammar introduced in 2.0. It is not a grammar sugar but a function provided by the framework upgrade.

Key Knowledge Points

  • Introducing generics: deferred declarations
  • How to declare and use generics
  • Benefits and principles of generics
  • Generic classes, generic interfaces, generic methods, generic delegates
  • Generic Constraints
  • Covariance, Inversion
  • Generic Cache

Generic application scenario: It is used to solve the problem of doing the same thing with a single method that satisfies different parameter types.

Generic declaration:

(No Write-Dead Parameter Type, only specify type when invoked.)

public static void Show<T>(T tParameter){
 //Code Content....
}

object type

public static void ShowObject(Object tParameter){
 Code Content....
}

Difference: object type is the parent of all types, through inheritance, a subclass can have all the attributes and behaviors of the parent class; wherever a parent class appears, it can be replaced by a subclass

The object type is a reference type. Assuming the value passed in is of type int, there will be a boxing operation, and there will be an unboxing operation when a method is called, which will affect performance.

What can a generic do when it is declared without specifying a parameter type, but when it is invoked, with specifying a type?

Requires compiler support + JIT support, depending on the upgrade of the compiler.

The compiler compiles with a placeholder of ~1, which is then replaced by a real type when the JIT compiles again.

 

Generic classes:

//statement
public class GenericClass<T>
{
  public T _t;
}
//Parameters can be multiple
public class GenericClass<T,S,X>
{
  public T _t;
  public S _s;
  public X _x;
}

//Use
GenericClass<int,string,char> t = new GenericClass<int,string,char>()
{
  _t = 123,
  _s = "123",
  _x = 'a'
};


//Common Class Inherits Generic Class
public class CommonClass
    :GenericClass<int,string,char>//Must be specified

//perhaps
     public class GenericClassChild<Eleven>:GenericClass<Eleven>
//You can also use public class GenericClassChild <Eleven>: GenericClass <int> where GenericClass <int> corresponds to a common type and can be inherited

Generic interface

public interface IGenericInterface<T>
{
 T getT(T t);//Return value of generic type
}


//Inheritance:
public class CommonClass
     :IGenericInterface<int>//Must be specified
{
  public int getT(int t)
  {
     .........
  } 
}

generic delegate

public delegate void SayHi<T>(T t);//generic delegate

Generic Constraints

//The type structure is as follows

public interface ISports
{
    void PingPang();
}

public interface Work
{
    void Work();
}

public class people
{
   public int Id{get;set;}   
   public string Name{get;set;}  
   public void Hi()
   {
       console.WriteLine("Hello!");
   }
}

public class Chinese:people,ISports,IWork
{
    public void Tradition()
    {
        console.WriteLine("The Chinese traditional culture is broad and profound");
    }

    public void SayHi()
    {
        console.WriteLine("Hello, have you eaten yet?");
    }

    public void PingPang()
    {
        console.WriteLine("Play table tennis....");
    }

    public void Work()
    {
        console.WriteLine("Work...");
    }
}

public class Hubei:Chinese
{
    public string Changjiang{get;set;}
    
    public void Majiang()
    {
        console.WriteLine("Mahjong.");
    }
}

public class Japanese:ISports
{
    public int Id{get;set;}
    public int Name{get;set;}
    public void PingPang()
    {
        console.WriteLine("Play table tennis....");
    }
    public void Hi()
   {
       console.WriteLine("Hello!");
   }
}

//Use
People people  = new People()
{
    Id = 123;
    Name= "Human beings"
};

Chinese people  = new Chinese()
{
    Id = 234;
    Name= "Chinese people"
};

Hubei people  = new Hubei()
{
    Id = 345;
    Name= "Hubei people"
};

Japanese people  = new Japanese()
{
    Id = 456;
    Name= "Japanese"
};


//Use
public class Constraint
{
    //Base class constraint (Int32 cannot be constrained) must be unsealed
    //1: All properties and methods of the base class can be used
    //2: Enforce that T must be a subclass of People or People
    public static void Show<T>(T tParameter)
        where T :People//constraint
    {
        console.WriteLine($"{tParameter.Id}_{tParameter.Name}"); //People classes can be accessed after adding constraints
        tParameter.Hi();
    }

    //Why not use this base class method?When the above method
    //public static void Show<T>(T tParameter)
       // WhereT: People, ISports, Iwork constraints can overlay, base classes cannot overlay all use constraints more flexible.
    public static void ShowBase(People tParameter)
    {
        console.WriteLine($"{tParameter.Id}_{tParameter.Name}"); //People classes can be accessed after adding constraints
        tParameter.Hi();
    }

}

Constraint.Show<People>(people);
Constraint.Show<Chinese>(Chinese);
Constraint.Show<Hubei>(Hubei);
Constraint.Show<Japanese>(Japanese);//This statement is incorrect because Japanese does not inherit people



//Interface Constraints
public static T Get<T>(T t)
   where T:ISports //Only ISport interfaces can be passed in
{
    t.PingPang();
    return t;
}

//Reference type constraint
public static T Get<T>(T t)
   where T:class //T must be a reference type to pass in
{
    T tNew = null;
    return t;
}

//Value Type Constraints
public static T Get<T>(T t)
   where T:struct //T must be a value type to pass in
{
    T tNew = default(T);//Default values will be given depending on T, if reference type is null, if int is 0, etc.
    return t;
}

//Parameterless constructor constraint
public static T Get<T>(T t)
   where T:new() //Parameterless constructor
{
    T tNew = new T();
    return t;
}

Covariance, Inversion

 

 

 

Posted by callmecheez on Fri, 19 Jun 2020 18:18:43 -0700