In generic classes, since you don't know what type the generic parameter T is, it may be a reference type or a value type, you cannot assign null, etc. to a generic type. How to assign initial values to generic objects, how to ensure the correctness of generics, etc., take using the generic document manager as an example:
Document manager is used to read and write documents from a queue. First create a generic manager. AddDocument() method to add a document to the queue. The IsDocumentAvailabe read-only property indicates whether there are any documents in the queue.
public class DocumentManager<T> { private readonly Queue<T> documentQueue = new Queue<T>(); public void AddDocument(T doc) { lock (this) { (doc); } } public bool IsDocumentAvailable { get { return > 0; } } }
1. Default value
Add a GetDocument() method to the DocumentManager<T> class to return a document in the queue. If there is a document in the queue, a document is returned; if there is no document in the queue, the default value is returned. However, for generic T, null cannot be assigned to the object of T, because it cannot be determined whether it is a reference type or a value type. In C#, we are provided with a default keyword, and the object of generic T is assigned a default value, such as: the reference type is null, the value type int, etc. is 0...
public T GetDocument() { T doc = default(T); lock (this) { if ( > 0) { doc = (); } } return doc; }
2. Constraint
If a generic class needs to call a method in a generic type, then constraints must be added to the generic. Otherwise, it is not possible to ensure that the declared generic type implements the corresponding type and has related methods. Create a document class Document, which implements the interface IDocument:
public interface IDocument { string Title { get; set; } string Content { get; set; } } public class Document : IDocument { public Document() { } public Document(string title, string content) { = title; = content; } public string Title { get; set; } public string Content { get; set; } }
Add method DisplayAllDocuments() to the generic document manager DocumentManager<T> so that the titles of all documents in the queue can be displayed. Before presenting the document title, cast type T to the IDocumnet interface to display the title:
public void DisplayAllDocuments() { foreach (T doc in documentQueue) { ((doc as IDocument).Title);//Captive conversion } }
However, if type T does not implement interface IDocument, an exception will appear when casting the type. If you add rty...catch processing to the method, it will be very performance-loss. Similarly, even if the type implements an interface IDocument, performance losses will occur when performing conversions.
Then, if the generic TDocument can be constrained so that the generic type must implement the interface IDocument, there will be no exception when casting the type. Even without casting, performance will be optimized. Therefore, the previous generic document manager was rewritten to (the previous T, rewritten to TDocument, which implies that it is a document type):
public class DocumentManager<TDocument> where TDocument : IDocument { //…… }
For generic document managers that implement constraints, you can handle any class that implements the IDocument interface. The DisplayAllDocuments() method is rewritten as:
public void DisplayAllDocuments() { foreach (TDocument doc in documentQueue) { (); } }
When called elsewhere, you can instantiate the generic type DocumentManager<TDocument> with the Document type. Because Document implements interface IDocument:
static void Main() { var dm = new DocumentManager<Document>(); (new Document("Title A", "Sample A")); (new Document("Title B", "Sample B")); (); if () { Document d = (); (); } }
Several constraints supported by generic types: struct (structural constraint, type T must be a value type), class (class constraint, type T must be a reference type), IFoo (type T must implement interface IFoo), new() (constructor constraint, type T must have a parameterless constructor), TOther (type T is derived from TOther, also known as "nude type constraint").
Generic constraints:
- Constructor constraints can only be defined for constructors without parameters, and constructor constraints cannot be defined for constructors with any parameters.
- Generics can have multiple constraints. For example: public class DocumentManager<TDocument> where TDocument: IDocument,new().
- Where can't define operators that must be implemented by generic types
3. Inheritance
Generic classes can also be inherited, such as in Queue<T>, which implements the interface IEnumerable<T> interface. Generic types can implement generic interfaces or derive from a class. Generic types can be derived from generic base classes:
class Base<T> { //............... } class Derived<T>:Base<T> { //............... }
The derived class can be a generic class or a non-generic type:
abstract class Calc<T> { public abstract T Add(T x, T y); public abstract T Sub(T x, T y); } class IncCalc: Calc<int> { public override int Add(int x, int y) { return x + y; } public override int Sub(int x, int y) { return x - y; } } class DoubleCalc : Calc<double> { public override double Add(double x, double y) { return x + y; } public override double Sub(double x, double y) { return x - y; } }
4. Static members
Static members of generic classes can only be shared in one instance:
class StaticDemo<T> { public static string Type; } static void Main() { StaticDemo<int>.Type = "int type"; StaticDemo<object>.Type = "Object type"; (StaticDemo<int>.Type);//Output: int type}
In fact, whenever a type is used to replace T in a generic, an instance type is created. Therefore, static fields in generic types will be regenerated in instances where different types replace generic T. This design also has benefits, which can provide the program with the concept of "generic cache", using static members of generics to store them in the cache, making them easy to call.
The above is a detailed explanation of the functions of c# generic classes. For more information about c# generic classes, please pay attention to my other related articles!