Bootstrap

C#中泛型

泛型

泛型的概念

泛型(generic)是C# 2.0推出的新语法,并不是语法糖,它是专门为处理多段代码在不同的数据类型上执行相同的指令的情况而设计的。

即泛型让不同的数据类型支持相同的业务逻辑。

泛型是一个复合类型,把多个类型混合一起作用,

比如:方法和泛型混到一起,叫泛型方法,类和泛型混在一起叫泛型类,接口和泛型混到一起,叫泛型接口,等等。

在C#中应用比较广的泛型:泛型方法,泛型类,泛型接口

泛型方法

泛型方法:调用时泛型参数类型可以省略

泛型定义时,是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _1.泛型方法
{
    internal class Program
    {
        static void Main(string[] args)
        {
            // 泛型的概念?
            /*
             泛型(generic)是C# 2.0推出的新语法,并不是语法糖,它是专门为处理多段代码在不同的数据类型上执行相同的指令的情况而设计的。

            即泛型让不同的数据类型支持相同的业务逻辑。

            泛型是一个复合类型,把多个类型混合一起作用,
            比如:方法和泛型混到一起,叫泛型方法,类和泛型混在一起叫泛型类,接口和泛型混到一起,叫泛型接口,等等。
            */

            // 在C#中应用比较广的泛型:泛型方法,泛型类,泛型接口

            Common.ShowInt(10, "hello");

            Console.WriteLine("------------------");
            Common.ShowInt(100);
            Common.ShowString("hello world");
            Common.ShowDateTime(DateTime.Now);

            // 泛型方法:调用时泛型参数类型可以省略
            // 泛型定义时,是延迟声明的:即定义的时候没有指定具体的参数类型,把参数类型的声明推迟到了调用的时候才指定参数类型。

            // 泛型方法参数的类型什么时候才确定?? 编译时     ( 时机:编译时,运行时)

            Console.WriteLine("------------------");
            Common.Show<int>(100);
            Common.Show<string>("hello world");
            Common.Show(DateTime.Now);
            Common.Show(new Program());

            //泛型优势:速度快且支持不同类型。
            //a.最大限度地重用代码(支持多种数据类型)。
            //b.保护类型的安全以及提高性能(和object相比,object会使用到装箱操作)。
            //c.语法优美

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();  // 开始计时
            Common.Show<int>(100);
            stopwatch.Stop(); // 结束计时

            TimeSpan ts = stopwatch.Elapsed;
            Console.WriteLine(ts.TotalMilliseconds);

            Stopwatch stopwatch2 = new Stopwatch();
            stopwatch2.Start();  // 开始计时
            Common.Show2(100);
            stopwatch.Stop(); // 结束计时

            TimeSpan ts2 = stopwatch2.Elapsed;
            Console.WriteLine(ts2.TotalMilliseconds);

            Console.ReadKey();
        }

        
    }
}

泛型方法参数的类型什么时候才确定?? 编译时 ( 时机:编译时,运行时)

需求:有一个静态类,它中有三个方法,分别显示类的类型名称,方法参数的类型名称,方法参数值
1。获取类型有两种方式:

a. typeof一般用来获取引用类型的变量类型。

b. GetType()是通用的。

typeof判断引用类型

GetType()可以获取值类型或引用类型的具体类型

public static void ShowInt(int i, string str)
{
    // typeof判断引用类型
    Console.WriteLine(typeof(Common).Name);
    Console.WriteLine(typeof(Common).Namespace);
    Console.WriteLine(typeof(Common).FullName);
    Console.WriteLine(typeof(Common).GUID);


    Console.WriteLine("---------------------");

    Console.WriteLine(str.GetType().Name);
    Console.WriteLine(str.GetType().Namespace);
    Console.WriteLine(str.GetType().FullName);
    Console.WriteLine(str.GetType().GUID);

    Console.WriteLine("---------------------");


    // GetType()方法是通用的,可以获取值类型或引用类型的具体类型。
    Console.WriteLine(i.GetType().Name);
    Console.WriteLine(i.GetType().Namespace);
    Console.WriteLine(i.GetType().FullName);
    Console.WriteLine(i.GetType().GUID);
}

三个方法:拥有相同的业务逻辑(相同指令),缺点:代码冗余,重复
 

public static void ShowInt(int i) {
    Console.WriteLine($"方法所在的类名:{typeof(Common).Name},"+
                      $"参数的类型名称:{i.GetType().Name},参数值:{i}");
}

public static void ShowString(string i)
{
    Console.WriteLine($"方法所在的类名:{typeof(Common).Name},"+
                      $"参数的类型名称:{i.GetType().Name},参数值:{i}");
}

public static void ShowDateTime(DateTime i)
{
    Console.WriteLine($"方法所在的类名:{typeof(Common).Name},"+
                      $"参数的类型名称:{i.GetType().Name},参数值:{i}");
}

public static void Show2(object i)
{
    Console.WriteLine($"方法所在的类名:{typeof(Common).Name},"+
                      $"参数的类型名称:{i.GetType().Name},参数值:{i}");
}

Show<T>是方法名称 <T>T是未知类型,不区分大小写,但建议使用大写,且尽量使用如下的字母:

T,K,V,M,N

定义时注意几点:

1。参数的未知类型在哪定义?(方法名称后面<>中)

2。参数的未知类型在哪里可以使用?(方法局部作用域)

3。参数的未知类型能定义几个?理论上是无限


public static void Show<T>(T i)
{
    Console.WriteLine($"方法所在的类名:{typeof(Common).Name},"+
                      $"参数的类型名称:{i.GetType().Name},参数值:{i}");
}

泛型类

泛型类定义:在类名后<T>

泛型类的作用域:整个类中

public class Calc<T>
{
    public void Add(T x, T y)
    {
        Console.WriteLine("相加");
    }

    public void Sub(T x, T y)
    {
        Console.WriteLine("相减");
    }

    public void Mul(T x, T y)
    {
        Console.WriteLine("相乘");
    }

    public void Div(T x, T y)
    {
        Console.WriteLine("相除");
    }
}

泛型接口

泛型接口和泛型类定义方式一样,在接口名称后使用<T>未知类型

只是方法签名,没有方法体,默认是公开的,不能添加修改符

public interface ICalc<T>
{
    T Add(T x, T y);
    T Sub(T x, T y);
    T Mul(T x, T y);
    T Div(T x, T y);
}

后续用不同的类实现这个接口即可

1.用于int类型数据的加减乘除
public class CalcInt : ICalc<int>
{
    public int Add(int x, int y)
    {
        return x + y;
    }

    public int Sub(int x, int y)
    {
        return x - y;
    }

    public int Mul(int x, int y)
    {
        return x * y;
    }

    public int Div(int x, int y)
    {
        return x / y;
    }
}
2.用于float类型数据的加减乘除 
public class CalcFloat : ICalc<float>
{
    public float Add(float x, float y)
    {
        return x + y;
    }

    public float Sub(float x, float y)
    {
        return x - y;
    }

    public float Mul(float x, float y)
    {
        return x * y;
    }

    public float Div(float x, float y)
    {
        return x / y;
    }
}

 泛型优势:速度快且支持不同类型。
            //a.最大限度地重用代码(支持多种数据类型)。
            //b.保护类型的安全以及提高性能(和object相比,object会使用到装箱操作)。
            //c.语法优美

Stopwatch 获取时间

stopwatch2.Start(); // 开始计时

stopwatch.Stop(); // 结束计时

TotalMilliseconds 获取总毫秒数

;