C#:泛型

泛型:拥有让多种类型共享一组代码的能力。

  • 在声明语句中,在方法名、类名、接口名、结构名、委托类型名后,使用一个"<占位符1,占位符2>"(如:List、Action<T1,T2>)来替代真实的数据类型这就完成了泛型的创建
  • 这些占位符被称为类型参数、使用了类型参数后方法变成了泛型方法、类变成了泛型类、接口变成了泛型接口...
  • 泛型类、泛型方法等不能直接使用,只有用真实的数据类型代替类型参数:如 List、Action<string,int>...才可以使用--而这一过程被称为特化
static void ShowInfo(int param)
{
    Console.WriteLine($"{param.GetType().FullName}--{param}");
}
static void ShowInfo(string param)
{
    Console.WriteLine($"{param.GetType().FullName}--{param}");
}
static void ShowInfo(double param)
{
    Console.WriteLine($"{param.GetType().FullName}--{param}");
}

通过观察,便可看出:上面的方法除了操作的数据类型不同外,在功能上是相同的;可以将代码改写成下面形式:
通过将方法声明为泛型方法,无论是预定义类型、用户自定义类型等,都可以共享同一组代码了。

static void ShowInfo<T>(T param)
{
    Console.WriteLine($"{param.GetType().FullName}--{param}");
}

泛型类

声明泛型类

  • 在类名后面放一对尖括号
  • 在尖括号中可以放置一个或多个占位符来表示希望提供的类型,这些占位符也成为类型参数
  • 在类体中,可以使用类型参数替代实际类型
class  MyStack<T>
{
    private int startPointer = 0;
    private T[] stackArray;
    public void Push(T item)
    {
        //压栈
    }
    public T Pop()
    {
        //弹栈
        return stackArray[stackArray.Length-1];
    }
}

使用泛型类

  • 为泛型参数提供实际的数据类型替补空缺--否则我们无法使用泛型类
  • 声明特化了的泛型实例
  • 使用实例调用方法
static void Main(string[] args)
{
    //使用int来替代T
    MyStack<int> myStack;
    //像普通类型创建实例那样,创建Mystack<int>类型实例
    myStack = new MyStack<int>();
    //调用方法
    myStack.Push(11);
    int popItem = myStack.Pop();
    Console.ReadLine();
}

泛型能够提高性能

class Program
{
    static void Main(string[] args)
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        Console.WriteLine($"开始:{stopwatch.ElapsedMilliseconds}");
        for (int i = 0; i < 1000; i++)
        {
            ShowInfo(i);
        }

        Console.WriteLine(stopwatch.ElapsedMilliseconds);
        stopwatch.Restart();
        Console.WriteLine($"重新开始:{stopwatch.ElapsedMilliseconds}");
        for (int i = 0; i < 1000; i++)
        {
            ShowInfo<int>(i);
        }

        Console.WriteLine(stopwatch.ElapsedMilliseconds);
        Console.ReadLine();
    }

    static void ShowInfo<T>(T param)
    {
        Console.WriteLine($"{param.GetType().FullName}--{param}");
    }

    static void ShowInfo(int param)
    {
        Console.WriteLine($"{param.GetType().FullName}--{param}");
    }
}

运行结果:

类型参数的约束:包括where子句和约束类型

//使用where子句,使类型参数T继承ICompare接口,这样parma1便可以使用CompareTo方法了
static bool IsLessThan<T>(T param1, T param2) where T : IComparable
{
    return param1.CompareTo(param2) < 0 ? true : false;
}

where子句

  • 如果需要对于单个类型参数,提供多个约束,则使用","隔开
static bool IsLessThan<T1,T2>(T1 param1, T2 param2) where T1 : struct,IComparable
{
    return param1.CompareTo(param2) < 0 ? true : false;
}

  • 如果需要对多个类型参数提供约束,则使用多个where子句--注意:where之间不需要使用","
static bool IsLessThan<T1, T2>(T1 param1, T2 param2) where T1 : struct, IComparable
                                                     where T2 : class
{
    return param1.CompareTo(param2) < 0 ? true : false;
}

约束类型:按照出现顺序约束一共下面几种

  • 主约束(只能有一个):
    • 类名---表明类型参数属于该类型或者继承了该类型
    • class---表明类型参数是一种引用类型
    • struct---表明类型参数是一种值类型
  • 次要约束(可以多个):
    • 接口名---此约束表明类型参数是实现了该接口的类型
  • 构造函数约束:多个约束时放在最后面
    • new()---此约束表明类型参数是一种带有公共无参构造函数的类型

下面展示一下约束类型的使用(仅为展示用,实际中可能并不会这样写)

static bool IsLessThan<T1, T2>(T1 param1, T2 param2) where T1 : Student, IComparable
                                                     where T2 : class,new()
{
    return param1.CompareTo(param2) < 0 ? true : false;
}

以上便是对泛型的概念的总结,关于泛型还有很多未总结的知识点,放在后面再写。

posted @ 2020-11-14 12:39  BigBosscyb  阅读(194)  评论(0编辑  收藏  举报