C # Generic details,

Source: Internet
Author: User

C # Generic details,

 

 

This article mainly talks about generics in c #, because generics play an important role in c # and play a key role in writing highly readable and high-performance code.

1. What is generic?

Generic is a very important new feature in C #2.0 and the Common Language Runtime Library (CLR.

When programming programs, we often encounter modules with very similar functions, but they process different data. However, there is no way to write multiple methods to process different data types. At this time, there is a problem. Is there a way to use the same method to handle incoming parameters of different types? The emergence of generics is dedicated to solving this problem. It can be seen that Microsoft is still very considerate.

2. Why should I use generics?

Next let's look at a piece of code.

public class GenericClass
    {
        public void ShowInt(int n)
        {
            Console.WriteLine("ShowInt print {0},ShowInt Parament Type Is {1}",n,n.GetType());
        }
        public void ShowDateTime(DateTime dt)
        {
            Console.WriteLine("ShowDateTime print {0},ShowDateTime Parament Type Is {1}", dt, dt.GetType());
        }
        public void ShowPeople(People people)
        {
            Console.WriteLine("ShowPeople print {0},ShowPeople Parament Type Is {1}", people, people.GetType());
        }
    }
static void Main(string[] args)
        {
            GenericClass generice = new GenericClass();
            generice.ShowInt(11);
            generice.ShowDateTime(DateTime.Now);
            generice.ShowPeople(new People { Id = 11, Name = "Tom" });

            Console.ReadKey();
        }

Display result:


We can see that the three methods have the same functions except the input parameters. In Version 1.1, there is no generic concept. What should I do. Some people think of inheritance of one of the three features of OOP. We know that in C #, all types are from the same type, that is, objects.

public class GenericClass
    {
        public void ShowObj(object obj)
        {
            Console.WriteLine("ShowObj print {0},ShowObj Parament Type Is {1}", obj, obj.GetType());
        }
    }
        static void Main(string[] args)
        {
            Console.WriteLine("*****************object调用*********************");
            generice.ShowObj(11);
            generice.ShowObj(DateTime.Now);
            generice.ShowObj(new People { Id = 11, Name = "Tom" });

            Console.ReadKey();
        }

Display result:


We can see that the goal is achieved. It solves the readability of the code, but this is another bad thing. This is actually a case of packing and unpacking, which will consume performance.

Finally, Microsoft launched the generic model at 2.0. Next we will use the generic method to implement this function.

Iii. Generic parameters

Before using the generic method, let's take a look at some knowledge about generics.

In a generic type or method definition, a type parameter is a placeholder of a specific type specified by the client when it instantiates a variable of a generic type. Generic class (GenericList<T>) Cannot be used as is, because it is not a real type; it is more like a type blueprint. To useGenericList<T>The client code must declare and instantiate the construction type by specifying the type parameter in the angle brackets. The type parameter of this specific class can be any type that the compiler can recognize. You can create any number of constructor type instances, each of which uses different type parameters, as shown below:

GenericList<float> list1 = new GenericList<float>();
GenericList<ExampleClass> list2 = new GenericList<ExampleClass>();
GenericList<ExampleStruct> list3 = new GenericList<ExampleStruct>();

InGenericList<T>In each instanceTThe parameter type will be replaced at runtime. With this replacement, we have created three separate type-safe valid objects by using a single class definition.

Iii. Generic Constraints

When defining generic classes, you can impose restrictions on several types of types that client code can use for type parameters when instantiating classes. If the client code attempts to instantiate a class using a type not allowed by the constraints, a compile-time error will occur. These restrictions are called constraints. UsewhereThe context keyword specifies the constraint. The following table lists the six types of constraints:


Where T: structure (the type parameter must be a value type. You can specify any value type except Nullable .)

Class MyClass<U>
         Where U : struct / / / constraint U parameter must be "value type"
  { }

  Public void MyMetod<T>(T t)
        Where T : struct
  {
  }

Where T: class (the type parameter must be of the reference type; this applies to any class, interface, delegate, or array type .)

Class MyClass<U>
         Where U : class / / / constraint U parameter must be "reference type"
  { }

  Public void MyMetod<T>(T t)
        Where T : class
  {
  }

Where T: new () (the type parameter must have a public constructor without parameters. When used with other constraints, the new () constraint must be specified at the end .)

class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
{
    // ...
}

Where T: <Base Class Name> (the type parameter must be the specified base class or be derived from the specified base class .)

public class Employee{}

public class GenericList<T> where T : Employee

Where T: <Interface Name> (the type parameter must be a specified interface or implement a specified interface. Multiple interface constraints can be specified. The constraint interface can also be generic .)

/// <summary>
     /// interface
     /// </summary>
     Interface IMyInterface
     {
     }

     /// <summary>
     /// Define a dictionary type
     /// </summary>
     /// <typeparam name="TKey"></typeparam>
     /// <typeparam name="TVal"></typeparam>
     Class Dictionary<TKey, TVal>
         Where TKey : IComparable, IEnumerable
         Where TVal : IMyInterface
     {
         Public void Add(TKey key, TVal val)
         {
         }
     }

Where T: U (the type parameter provided for T must be a parameter provided for U or derived from a parameter provided for U. That is to say, the T and U parameters must be the same)

class List<T>
{
    void Add<U>(List<U> items) where U : T {/*...*/}
}


The above is a simple example of six generic types. Of course, generic constraints are not only applicable to classes and interfaces, but also for generic methods and generic delegation.

Iii. Generic Method

Public class GenericClass
     {
         Public void ShowT<T>(T t)
         {
             Console.WriteLine("ShowT print {0}, ShowT Parament Type Is {1}", t, t.GetType());
         }
     }
Static void Main(string[] args)
         {
             Console.WriteLine("*****************generic method call *********************");
             generice.ShowT<int>(11);
             generice.ShowT<DateTime>(DateTime.Now);
             generice.ShowT<People>(new People { Id = 11, Name = "Tom" });

             Console.ReadKey();
         }

Display result:


The same is true. Now we have finally achieved the desired effect. We can see that no matter how the call is made, the type we get is the original type. We know that object acquisition uses the inheritance feature. When the compiler compiles, the input parameters will be boxed. When we obtain the feature, we need to unpack it again, this method will consume performance. So what is the principle of implementation of generic methods? First, we need to know that generics are a syntactic sugar. When we call a generic method, the compiler will determine the type of the input parameter to generate a copy method. This copy method is similar to the original method, so there will be no packing and unpacking operations, and there will be no loss performance.

Iv. Generic Type

Generic classes encapsulate operations that are not specific to specific data types.

Generally, creating a generic class starts from an existing specific class and changes the type to a type parameter one by one until the generalization and availability reach the optimal balance.

When creating your own generic classes, consider the following important considerations:

  • Which types are generalized as type parameters.

Generally, the more types that can be parameterized, the more flexible the code and the higher the reusability. However, excessive generalization may make it difficult for other developers to read or understand the code.

  • Constraints (if any) to be applied to type parameters

 

One of the useful rules is that the application has the maximum constraint and can still process the types that must be processed. For example, if you know that generic classes are only used for reference types, apply class constraints. This prevents the class from being accidentally used for the value type, and enables you to use the as operator on T and check the null value.

 

  • Whether to break down generic behaviors into basic classes and subclasses.

    Because generic classes can be used as base classes, the same design considerations for non-generic classes also apply here. See the following topic for the rules for inheriting from the generic base class.

  • Implements one or more generic interfaces.

  • class BaseNode { }
    class BaseNodeGeneric<T> { }
    
    // concrete type
    class NodeConcrete<T> : BaseNode { }
    
    //closed constructed type
    class NodeClosed<T> : BaseNodeGeneric<int> { }
    
    //open constructed type 
    class NodeOpen<T> : BaseNodeGeneric<T> { }

    V. Generic Interfaces

    • Define a generic interface:
    • interface IMyGenericInterface<T>{}
      • One interface can define multiple types of parameters, as shown below:
      • interface IMyGenericInterface<TKey,TValue>{}
        • A specific class can implement a closed constructor interface, as shown below:
        • Interface IBaseInterface<T> { }
          
          Class SampleClass : IBaseInterface<string> { }//If T has constraints, the string type must satisfy the constraints of T
          

6. Generic Delegation

A delegate can define its own type parameters. Code that references a generic delegate can specify a type parameter to create a closed constructor type, just like instantiating a generic class or calling a generic method, as shown in the following example:

Class Program
     {
         Static void Main(string[] args)
         {
             Del<int> m1 = new Del<int>(Notify);
             m1.Invoke(1111);
             Del<string> m2 = new Del<string>(Notify);
             m2.Invoke("string");

             Console.ReadKey();
         }

         Public delegate void Del<T>(T item);
         Public static void Notify(int i) { Console.WriteLine("{0} type is {1}", i,i.GetType()); }
         Public static void Notify(string str) { Console.WriteLine("{0} type is {1}", str, str.GetType()); }
       
     }

Running result:


7. Default keyword in generic code: Default

One problem that occurs in generic classes and generic methods is how to assign the default value to parameterized type T when the following conditions are unknown:

  • T is the reference type or value type.

  • If T is of the value type, whether it is a value or a structure.

Given a variable T of the parameterized type t, the Statement T = null is valid only when t is of the reference type; only when T is of the numerical type rather than the structure, statement t = 0 can be used normally. The solution is to useDefaultKeyword. This keyword returns NULL for the reference type and zero for the value type. For the structure, this keyword returns each structure member whose Initialization is zero or empty, depending on whether the structure is a value type or a reference type.

namespace MyGeneric
{
    class Program
    {
        static void Main(string[] args)
        {
            object obj1=GenericToDefault<string>();
            object obj2 = GenericToDefault<int>();
            object obj3 = GenericToDefault<StructDemo>();
            Console.ReadKey();
        }
        public static T GenericToDefault<T>() 
        {
            return default(T);
        }
    }
    public struct StructDemo
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

Running result:




 

 

Link: https://www.cnblogs.com/hhzblogs/p/7820005.html

 


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.