C#中的泛型

目录

一、泛型的类型参数T

二、创建泛型接口

1.接口及约束定义

2.示例

三、创建泛型方法


        泛型是C# 和公共语言运行库(CLR)中的一个功能,这是一种可以使程序支持不同类型的技术。它将类型参数的概念引入.NET Framework中,类型参数将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法。即,泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。

        泛型是用于处理算法、数据结构的一种编程方法。泛型的目标是采用广泛适用和可交互性的形式来表示算法和数据结构,以使它们能够直接用于软件构造。泛型类、结构、接口、委托和方法可以根据它们存储和操作的数据的类型来进行参数化。泛型能在编译时提供强大的类型检查,减少数据类型之间的显示转换、装箱操作和运行时的类型检查。泛型类和泛型方法同时具备可重用性、类型安全和效率高等特性,这是非泛型类和非泛型方法无法具备的。泛型通常用在集合和在集合上运行的方法中。泛型主要是提高了代码的重用性。        

一、泛型的类型参数T

        泛型的类型参数T 可以看作 是一个占位符,它不是一种类型,它仅代表了某种可能的类型 。在定义泛型 时T 出现的位置可以在使用时用任何类型来代替。
  
类型参数T的命名准则如下:

//使用描述性名称命名泛型类型参数,除非单个字母名称完全可以让人了解它表示的含义,而描述性名称不会有更多的意义。
public interface ISessionChannel
public delegate TOutput Converter

//将T作为描述性类型参数名的前缀
public interface ISessionChannel
{
    TSession Session{get;}
}

二、创建泛型接口

1.接口及约束定义

        泛型接口的声明形式如下:

interface [接口名] 
{
    [接口体]
}

        声明泛型接口时,与声明一般接口的唯一区别是增加了一个。一般来说,声明泛型接口与声明非泛型接口遵循相同的规则。泛型类型声明所实现的接口必须对所有可能的构造类型都保持唯一。否则就无法确定该为某些构造类型调用哪个方法。

        在实例化泛型时也可以使用约束对类型参数的类型种类施加限制,约束是使用where上下文关键字指定的。下面列出了6种类型的约束。

约束

说明

T:结构

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

T:类

类型参数必须是引用类型。这一点也适用于任何类、接口、委托或数组类型

T:new()

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

T:<基类名>

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

T:<接口名称>

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

T:U

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

2.示例

// 泛型
using System.ComponentModel;

namespace _01
{
    /// 
    /// 创建一个泛型接口
    /// 接口中调用CreateInstance方法
    /// 
    /// 
    public interface IGenericInterface
    {
        T CreateInstance();
    }
 
    /// 
    /// 实现上面泛型接口的泛型类,创建一个公共方法CreateInstance
    /// 派生约束where T : TI(T要继承自TI)
    /// 构造函数约束where T : new()(T可以实例化)
    /// 
    /// 
    /// 
    public class Factory : IGenericInterface where T : TI, new()
    {
        public TI CreateInstance()
        {
            return new T();
        }
    }

    class Program
    {
        /// 
        /// 注释掉的部分是一种实现,但会引起警告CA1859
        /// 内联临时变量后不需要实例化接口,并且解决警告CA1859
        /// 输出指定泛型的类型
        /// 
        static void Main()
        {
            //实例化接口
            //IGenericInterface factory = new Factory();
            //Console.WriteLine(factory.CreateInstance().GetType().ToString());
            Console.WriteLine(new Factory().CreateInstance().GetType().ToString());
            Console.ReadLine();
        }
    }
}
/*运行结果:System.Data.DataTable    */

三、创建泛型方法

        泛型方法是在声明中包括了类型参数T的方法。泛型方法可以在类、结构或接口声明中声明,这些类、结构或接口本身可以是泛型或非泛型的。如果在泛型类型声明中声明泛型方法,则方法体可以同时引用该方法的类型参数T和包含该方法的声明的类型参数T。泛型方法可以使用多类型参数进行重载。       

//泛型方法的声明形式如下:
[修饰符] Void [方法名] <类型参数T>
{
    [方法体]
}

         示例:在数组中查找某一数值的位置

// 泛型方法
// 通过定义一个泛型方法,查找数组中某个数字的位置
namespace _02
{
    public class Finder										//建立一个公共类Finder
    {
        /// 
        /// 创建泛型方法
        /// 
        /// 泛型类型
        /// 数组变量
        /// 指定的某个数值常量
        /// "i,从0起的数组索引号"
        public static int Find(T[] items, T item)
        {
            for (int i = 0; i < items.Length; i++)	//调用for循环
            {
                if (items[i]!.Equals(item))		    //调用Equals方法比较两个数
                {
                    return i;						//返回相等数在数组中的位置
                }
            }
            return -1;								//如果不存在指定的数,则返回-1
        }
    }
    class Program
    {
        /// 
        /// 在泛型数组中查询并输出=6的元素的索引号
        /// 
        static void Main(string[] args)
        {
            int i = Finder.Find([1, 2, 3, 4, 5, 6, 8, 9], 6); 
            Console.WriteLine("6在数组中的位置:" + i.ToString());
            Console.ReadLine();
        }
    }
}
/*6在数组中的位置:5    */

        用泛型方法来表达,思路太清晰了。

你可能感兴趣的:(c#,开发语言)