第21节、C#泛型方法、类、接口、委托

1、C#泛型

泛型是一种通用的数据类型,可以存储任何类型的数据,程序中使用泛型减少过程中复杂的装箱与拆箱操作,提高程序效率。

为什么选择泛型

实际开发中:某写功能实现方式相似仅参数类型不同,拷贝修改数据类型是能完成功能,可项目代码重复冗余。我们会想到定义Object类型处理,可曾想到操作反复的拆装与装箱带来的系统开销,影响效率。此时泛型就很好解决该问题了。看范例理解。

一、泛型方法

示范1.1:简单多个相似方法功能

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

namespace ConsoleApplication1
{
    public class 泛型1
    {
        public static void Main(string[] args)
        {
            Print pr = new Print();
            pr.IntData(1);
            pr.StrData("字符串");
            pr.TimeDate(DateTime.Now);
            Console.ReadKey();
        }
    }

    public class Print
    {
        public void IntData(int prams)
        {
            Console.WriteLine("参数类型是:{0}型", prams.GetType().Name);
        }

        public void StrData(string prams)
        {
            Console.WriteLine("参数类型是:{0}型", prams.GetType().Name);
        }

        public void TimeDate(DateTime prams)
        {
            Console.WriteLine("参数类型是:{0}型", prams.GetType().Name);
        }
    }
}

输出:

 认真观察,上面的三个方法分别输出参数类型,方法除了参数类型不同以外,实现的功能及代码基本一致!其实我们解决第一个参数就可以。可以使用基类型Object定义参数类型。

示范1.2:Object定义类型

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

namespace ConsoleApplication1
{
    public class 泛型1
    {
        public static void Main(string[] args)
        {
            Print pr = new Print();
            pr.objectData(1);
            pr.objectData("字符串");
            pr.objectData(DateTime.Now);
            Console.ReadKey();
        }
    }

    public class Print
    {
        public void objectData(object prams)
        {
            Console.WriteLine("参数类型是:{0}型", prams.GetType().Name);
        }
    }
}

输出:

 这样调整功能实现了,可如果objectData方法很多业务理解,就需要拆箱等操作。下面就示范泛型实现。

示范1.3:泛型方法

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

namespace ConsoleApplication1
{
    public class 泛型1
    {
        public static void Main(string[] args)
        {
            Print pr = new Print();
            pr.objectData<int>(1);         //可以给<指定类型>
            pr.objectData(1);              //<T>可以省略,自动根据参数推算
            pr.objectData("字符串");
            pr.objectData(DateTime.Now);
            Console.ReadKey();
        }
    }

    public class Print
    {
        public void objectData<T>(T prams)
        {
            Console.WriteLine("参数类型是:{0}型", prams.GetType().Name);
        }
    }
}

输出:

 二、泛型类

声明泛型类语法格式:

修饰符 Class 类名<类型参表>
{
 类体
} 

范例2.1:泛型类

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

namespace ConsoleApplication1
{
    public class 泛型1
    {
        public static void Main(string[] args)
        {
            Print<string> pr = new Print<string>("字符串");
            pr.objectData();

            Print2<int> pr1 = new Print2<int>();
            pr1.objectData(1);
            Console.ReadKey();
        }
    }

    public class Print<T>
    {
        private T data;
        public Print(T Data)
        {
            data = Data;
        }
        public void objectData()
        {
            Console.WriteLine("参数类型是:{0}型", data.GetType().Name);
        }
    }

    public class Print2<T>
    {
        public void objectData(T t)
        {
            Console.WriteLine("参数类型是:{0}型", t.GetType().Name);
        }
    }
}

输出:

 三、泛型接口

声明泛型接口语法格式:

//定义泛型接口
修饰符 Interface 接口名<类型形参表>
{
接口体
}

//泛型类实现泛型接口
Class 类名<类型形参表>:基接口<类型形参表>
{
 类体
}

示范3.1:声明泛型接口

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

namespace ConsoleApplication1
{
    interface 泛型接口<T>
    {
        void GetDataType(T type);
    }
}

示范3.2:泛型类实现泛型接口

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

namespace ConsoleApplication1
{
    public class 泛型1
    {
        public static void Main(string[] args)
        {
            GetData<int> g1 = new GetData<int>();
            g1.GetDataType(5);
            GetData<string> g2 = new GetData<string>();
            g2.GetDataType("泛型接口");
            Console.ReadKey();
        }
    }

    public class GetData<T> : 泛型接口<T>
    {
        public void GetDataType(T t)
        {
            Console.WriteLine("参数类型是:{0}型,值是:{1}", t.GetType().Name,t);
        }
    }
    
}

输出:

四、泛型委托

示范4.1:泛型委托声明

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

namespace ConsoleApplication1
{
    public delegate void Mydelegate<T>(T t);
    public class 泛型委托<T>
    {
        public void GetDateType(T t)
        {
            Console.WriteLine("参数类型是:{0}型,值是:{1}", t.GetType().Name,t);
        }

    }
}

示范4.2:泛型委托调用

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

namespace ConsoleApplication1
{
    public class 泛型1
    {
        public static void Main(string[] args)
        {
            泛型委托<int> obj = new 泛型委托<int>();
            Mydelegate<int> de = obj.GetDateType;
            de(6);

            泛型委托<string> obj1 = new 泛型委托<string>();
            Mydelegate<string> de1 = obj1.GetDateType;
            de1("泛型委托");
            Console.ReadKey();
        }
    }
}

输出:

 五、使用泛型约束

定义泛型类时,可以限制在实例化类客户端代码的参数,当客户代码使用了被约束类型进行实例操作时出现编译错误,使用关键字 Where来实现

约束说明

T:struct

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

T:class

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

T:new()

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

T:<基类名>

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

T:<接口名称>

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

T:U

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

 

原文地址:https://www.cnblogs.com/liuzz/p/14546416.html