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