zoukankan      html  css  js  c++  java
  • C#中泛型类,泛型方法,泛型约束实际应用

    前言

    所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型。

    泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。在定义泛型类时,在对客户端代码能够在实例化类时,可以用类型参数的类型种类施加限制。在搭建底层框架时,是最常见的编程方式。

    泛型类

    泛型类范例:

    namespace ORDER.SYSTEM.DAL.Data
    {
        public abstract class AgentBase<T> where T : class, new()
        {
    
            //私有实例
            private static T _instance;
    
            // 定义一个标识确保线程同步
            private static readonly object locker = new object();
    
            /// <summary>
            /// 返回单例对象
            /// </summary>
            /// <returns></returns>
            public static T Instance()
            {
                if (_instance == null)
                {
                    lock (locker)
                    {
                        if (_instance == null)
                        {
                            switch (typeof(T).FullName)
                            {
                                case "ORDER.SYSTEM.BLL.TextImpl":
                                    _instance = new T(); //此处的T表示命名空间的下的某个类被托管或重写,只保留功能
                                    break;
                                default:
                                    _instance = new T();
                                    break;
                            }
                        }
                    }
                }
                return _instance;
            }
    
        }
    }
    

    泛型类的目的是为了约束泛型方法传参数类型或返回值类型。

    泛型方法

    C# 2.0中,方法可以定义特定于其执行范围的泛型参数,如下所示:

    public class MyClass<T>
    {
        //指定MyMethod方法用以执行类型为X的参数
        public void MyMethod<X>(X x) 
        {
            //
        }
    
        //此方法也可不指定方法参数
        public void MyMethod<X>() 
        {
            //
        }
    }   
    

    即使包含类不适用泛型参数,你也可以定义方法特定的泛型参数,如下所示:

    public class MyClass
    {
        //指定MyMethod方法用以执行类型为X的参数
        public void MyMethod<X>(X x) 
        {
            //
        }
    
        //此方法也可不指定方法参数
        public void MyMethod<X>() 
        {
            //
        }
    }
    

    注意:属性和索引器不能指定自己的泛型参数,它们只能使用所属类中定义的泛型参数进行操作。

    在调用泛型方法的时候,你可以提供要在调用场所使用的类型,如下所示:

    //调用泛型方法
    MyClass myClass = new MyClass();
    myClass.MyMethod<int>(3);
     
    泛型推理:
    在调用泛型方法时,C#编译器足够聪明,基于传入的参数类型来推断出正确的类型,并且它允许完全省略类型规范,如下所示:

    //泛型推理机制调用泛型方法
    MyClass myClass = new MyClass();
    myClass.MyMethod(3);

    注意:泛型方法无法只根据返回值的类型推断出类型,代码如下:

    public GenericMethodDemo()
    {        
        MyClass myClass = new MyClass();
        /****************************************************
        无法从用法中推理出方法“GenericMethodDemo.MyClass.MyMethod<T>()”的类型参数。
        请尝试显式指定类型参数。
        ***************************************************/
        int number = myClass.MyMethod();
    }
    
    public class MyClass
    {
        public T MyMethod<T>() 
        {
            //
        }
    }
    

    泛型方法中泛型参数的约束,如下:

    public class MyClass
    {
        
        public void MyMethod<X>(X x) where X:IComparable<X>
        {
            //
        }
    }
    

    .NET泛型约束

    如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。

    下表列出了五种类型的约束:

    约束说明

    T:struct

    类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。

    T:class

    类型参数必须是引用类型,包括任何类、接口、委托或数组类型。

    T:new()

    类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。

    T:<基类名>

    类型参数必须是指定的基类或派生自指定的基类。

    T:<接口名称>

    类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。

    T:U

    为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束.

     

    派生约束

    1.常见的

    public class MyClass5 where T :IComparable { }

    2.约束放在类的实际派生之后

    public class B { }

    public class MyClass6 : B where T : IComparable { }

    3.可以继承一个基类和多个接口,且基类在接口前面

    public class B { }

    public class MyClass7 where T : B, IComparable, ICloneable { }

     

    构造函数约束

    1.常见的

    public class MyClass8 where T : new() { }

    2.可以将构造函数约束和派生约束组合起来,前提是构造函数约束出现在约束列表的最后

    public class MyClass8 where T : IComparable, new() { }

     

    值约束

    1.常见的

    public class MyClass9 where T : struct { }

    2.与接口约束同时使用,在最前面(不能与基类约束,构造函数约束一起使用)

    public class MyClass11 where T : struct, IComparable { }

     

    引用约束

    常见的

    public class MyClass10 where T : class { }

    多个泛型参数

    public class MyClass12<T, U> where T : IComparable where U : class { }

  • 相关阅读:
    互联网思维(1)
    互联网思维
    WLAN和WIFI的区别
    ping操作
    一篇关于正则表达式的小结
    javascript正则表达式
    为什么原型继承很重要 – SegmentFault
    JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型
    【转】前端开发文档规范
    我的第一篇博文
  • 原文地址:https://www.cnblogs.com/ydcnblog/p/9294382.html
Copyright © 2011-2022 走看看