首页 > 技术文章 > 泛型接口的实现和调用

May-day 2017-02-09 14:47 原文

一,什么是泛型?

泛型:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。在.NET类库中处处都可以看到泛型的身影,尤其是数组和集合中,泛型的存在也大大提高了程序员的开发效率。

二,泛型的优点:

1>当在一个功能模块实现就是同一种方法,而类型不同导致系统实现多次的拆箱和装箱的操作,这将在托管堆上分配和回收大量的变量,若数据量大,则性能损失非常严重。 在处理引用类型时,虽然没有装箱和折箱操作,但将用到数据类型的强制转换操作,增加处理器的负担,而泛型刚好可以解决这个问题

2>使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。

3>在MSDN中用ArrayList的代码介绍非泛型时的缺点,地址:https://msdn.microsoft.com/zh-cn/library/b5bx6xee.aspx:

在公共语言运行时和 C# 语言的早期版本中,通用化是通过在类型与通用基类型 Object 之间进行强制转换来实现的,泛型提供了针对这种限制的解决方案。 通过创建泛型类,您可以创建一个在编译时类型安全的集合。

使用非泛型集合类的限制可以通过编写一小段程序来演示,该程序使用 .NET Framework 类库中的 ArrayList 集合类。 ArrayList 是一个使用起来非常方便的集合类,无需进行修改即可用来存储任何引用或值类型。

 // The .NET Framework 1.1 way to create a list:
            System.Collections.ArrayList list1 = new System.Collections.ArrayList();
            list1.Add(3);
            list1.Add(105);

            System.Collections.ArrayList list2 = new System.Collections.ArrayList();
            list2.Add("It is raining in Redmond.");
            list2.Add("It is snowing in the mountains.");

但这种方便是需要付出代价的。 添加到 ArrayList 中的任何引用或值类型都将隐式地向上强制转换为 Object。 如果项是值类型,则必须在将其添加到列表中时进行装箱操作,在检索时进行取消装箱操作。 强制转换以及装箱和取消装箱操作都会降低性能;在必须对大型集合进行循环访问的情况下,装箱和取消装箱的影响非常明显

三,在使用泛型处理类似情况,客户端代码基于每个实例指定这些类要使用的具体数据类型的方式。这样将不再需要向上强制转换为 T:System.Object,同时,也使得编译器可以进行类型检查。这样增强了代码的通用性和减少代码的重复性。例子如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InterfaceTdemo
{
    //定义泛型接口
    public interface ISay<T, U> where T : class
    {
        void SpeakEn(T t);

        void SpeakCh(U u);
    }

    //定义实体类
    public class English
    {
        public string Content { get; set; }
    }

    //定义实体类
    public class Chinese
    {
        public string Content { get; set; }
    }
    //定义实体类
    public class English2
    {
        public string Content { get; set; }
    }

    //定义实体类
    public class Chinese2
    {
        public string Content { get; set; }
    }

    //实现泛型接口中的方法
    public class Say : ISay<English, Chinese>    //继承并实现接口
    {
        public void SpeakEn(English en)
        {
            Console.WriteLine(en.Content);
        }

        public void SpeakCh(Chinese ch)
        {
            Console.WriteLine(ch.Content);
        }
    }

    //实现泛型接口中的方法2
    public class Say2 : ISay<English2, Chinese2>    //继承并实现接口
    {
        public void SpeakEn(English2 en)
        {
            Console.WriteLine(en.Content);
        }

        public void SpeakCh(Chinese2 ch)
        {
            Console.WriteLine(ch.Content);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            English en = new English();
            en.Content = "English";
            Chinese ch = new Chinese();
            ch.Content = "中文";
            English2 en2 = new English2();
            en2.Content = "English2";
            Chinese2 ch2 = new Chinese2();
            ch2.Content = "中文2";

            //通过传不同的类型实现调用不同的方法,分别调用相同接口不同类型的实现方法
            ISay<English, Chinese> Is = new Say();
            Is.SpeakCh(ch);
            Is.SpeakEn(en);

            ISay<English2, Chinese2> Is2 = new Say2();
            Is2.SpeakCh(ch2);
            Is2.SpeakEn(en2);
        }
    }
}

 综上:

1》与 ArrayList 相比,使用泛型就是添加的唯一语法是声明和实例化中的类型参数,ISay<English2, Chinese2> Is2 = new Say2();而这类型参数就是你自己传过去

2》泛型编程的思想:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。

推荐阅读