c#泛型初学

一.泛型的概念

泛型是C#2.0推出的新语法

“泛型”的字面意思就是 广泛的类型。类、接口和方法代码可以同应用于非常广泛的类型,代码与它们可以操作的数据类型不再绑定在一起,同一套代码可以用于多种数据类型,这样,不仅可以服用代码,降低耦合,而且可以提高代码的可读性和安全性。

1.一个简单的demo

//user类

public class User
{
public string name; // 姓名
public int age; // 年龄
public User(string name, int age)
{
this.name = name;
this.age = age;
}
}
User user1 = new User("李宁",21);
            User user2 = new User("耐克", 21);
            User user3 = new User("阿迪", 21);
            //声明Dictionary泛型变量
            //key的类型为int,Value的类型为User
            Dictionary<int, User> users = new Dictionary<int, User>();
            //向users添加"元素","元素"的key不能重复
            users.Add(2,user1);
            users.Add(3, user2);
            users.Add(5, user3);
            foreach (var p in users)
            {
                Console.WriteLine(p.Key);
                Console.WriteLine(p.Value.name);
                Console.WriteLine(p.Value.age);
            }
            foreach (var u in users.Values)
            {
                Console.WriteLine(u.name);
                Console.WriteLine(u.age);
            }

这里利用字典类进行解释泛型的概念

 二.泛型约束

在写程序的时候经常看到如下代码:

public class MyClass5<T> where T :IComparable { }

在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。

下表列出了五种类型的约束:

 

约束说明

T:struct

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

T:class

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

T:new()

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

T:<基类名>

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

T:<接口名称>

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

T:U

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

三.泛型的协变和逆变

“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。

“逆变”则是指能够使用派生程度更小的类型。

解释的很正确,大致就是这样,不过不够直白。

直白的理解:

“协变”->”和谐的变”->”很自然的变化”->string->object :协变。

“逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。

比如说你新建一个动物类(Animal),以及猫类(Cat),猫类为子类,继承与动物类

Animal animal = new Animal();
Cat cat = new Cat();
Animal animal2 = new Cat();
List<Animal> listanimal = new List<Animal>();
List<Cat> listcat = new List<Cat>();

上述这些实例都没有问题,

但是如下一行代码,是一定会报错

List<Animal> listanimal_cat = new List<Cat>();

错误的原因是List<Animal>与List<Cat>之间并没有父子关系

这时就可以用到协变和逆变了

//协变

IEnumerable<Animal> listanimal_cat = new List<Cat>();

可以F12查看IEnumerable的定义,

使用了协变以后,左边声明的是基类,右边可以声明基类或者基类的子类

//逆变

Action<Animal> b = (target) => { Console.WriteLine(target.GetType().Name); };
Action<Cat> d = b;
d(new Cat());

逆变我还是有些不理解,具体请翻阅微软官方文档

转载于:https://www.cnblogs.com/dotnet261010/p/9034594.html

posted @ 2021-08-24 10:10  rookiexwang  阅读(50)  评论(0编辑  收藏  举报