C#泛型(三)

主要的内容:

<1>.原理性的东西----” 泛型的协变和逆变 “

  <2>.以及常用的接口----” IEnumerable 及其泛型版的IEnumerable<out T> “

<泛型的协变与逆变|泛型修饰符‘out’与‘in’>

先知道协变和逆变主要是用在泛型的接口和委托上就可以了,下面我们通过一个例子来看看:

我们知道接口是可以体现多态的,当然接口体现的多态注重的功能上的多态,这和抽象类不同,抽象类更注重的是建立在血缘关系上的多态。

知道接口是可以体现多态的之后,我们来看看一个相关的例子--

实例:鸟和飞机都会飞,把飞定义成一个接口,在定义2个类

public interface IFlyable
    {
        void fly();
    }
    class Bird:IFlyable
    {
        public void fly()
        {
            Console.WriteLine("鸟儿飞!");
        }
    }
    class Plane:IFlyable
    {
        public void fly()
        {
            Console.WriteLine("飞机飞!");
        }
    }

下面看看接口体现的多态性:

            IFlyable ifly; 

            ifly = new Bird();
            ifly.fly();

            ifly = new Plane();
            ifly.fly();

运行结果:

鸟儿飞!

飞机飞!

了解了接口的多态性后我们再来看一个例子:

这里定义了2个类 Animal 和 Cat (Cat继承了Animal)

  public class Animal
    {
    }

    public class Cat:Animal
    {
    }

继续往下看:

Cat cat = new Cat();

下面这句代码,cat向animal转,子类向父类转换,这时cat会隐式转换为animal 我们说“儿子像父亲” 这是完全可以理解的

Animal animal = cat;

但是 说”父亲像儿子“ 这是说不过去的 ,但是有的时候如果儿子坑爹,强制转换了一下还是可以的

cat = (Cat)animal;

(协变)

            List<Cat> catArray = new List<Cat>();
            List<Animal> animalArray = catArray;

如果是上面说的类,这样写是可以的,但是这里是会报错的  如图

继续往下看 这样写却可以:

            IEnumerable<Cat> lCat = new List<Cat>();
            IEnumerable<Animal> lAnimal = lCat;

对 IEnumerable<Cat> 转到定义 如图 我们发现这里多了一个 “out” 关键字

概念引入:

1.对于泛型类型参数,out 关键字指定该类型参数是协变的。 可以在泛型接口和委托中使用 out 关键字。“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。

时间: 2024-10-16 10:26:14

C#泛型(三)的相关文章

Java 泛型 三

一.泛型初衷 Java集合不会知道我们需要用它来保存什么类型的对象,所以他们把集合设计成能保存任何类型的对象,只要就具有很好的通用性.但这样做也带来两个问题: –集合对元素类型没有任何限制,这样可能引发一些问题:例如想创建一个只能保存Sting对象的集合,但程序也可以轻易地将int对象"丢"进去,所以可能引发异常. –由于把对象"丢进"集合时,集合丢失了对象的状态信息,集合只知道它盛装的是Object,因此取出集合元素后通常还需要进行强制类型转换.这种强制类型转换既

06.C#泛型约束和高级泛型(三章3.3-3.4)

吃午饭前继上篇泛型再写一篇关于泛型的文章,虽然总是被博客园移出首页,文章不精确实是大问题啊,会再接再厉的.进入正题. 先来说下泛型约束.当我们在使用泛型的时候通常会希望使用泛型实参时,参数能具备某一些特性,这时"泛型约束"来了,它能帮助我们在传入泛型参数,该参数要实现先前指定的约束.有4种约束可用,如下: 引用类型约束:确保使用的类型参数是引用类型(T:class,且必须是类型参数指定的第一个约束),类型实参任何类.接口.数组.委托.或者已知是引用类型的另一个类型参数. 值类型约束:表

java泛型中&lt;?&gt;和&lt;T&gt;有什么区别?

public static void printColl(ArrayList<?> al){                Iterator<?> it = al.iterator();                while(it.hasNext())                {                        System.out.println(it.next().toString());                }?和T都表示不确定的类型  但如

java泛型中&lt;?&gt;和&lt;T&gt;区别

public static void printColl(ArrayList<?> al){                Iterator<?> it = al.iterator();                while(it.hasNext())                {                        System.out.println(it.next().toString());                }?和T都表示不确定的类型  但如

java基础知识 泛型

泛型 泛型类型的参数类型必须是引用类型如 ArrayList<int> list = new ArrayList<int>();  //错误 ArrayList<Integer> list = new ArrayList<Integer>();  //正确list.add(5);  //正确  自动打包(装箱)机制int i = list.get(0); //正确,如果元素是包装类型,如Integer,Double,Character,可以直接将这个元素赋给

Java中泛型区别以及泛型擦除详解

一.引言 复习javac的编译过程中的解语法糖的时候看见了泛型擦除中的举例,网上的资料大多比较散各针对性不一,在此做出自己的一些详细且易懂的总结. 二.泛型简介 泛型是JDK 1.5的一项新特性,一种编译器使用的范式,语法糖的一种,能保证类型安全.[注意:继承中,子类泛型数必须不少于父类泛型数] 为了方便理解,我将泛型分为普通泛型和通配泛型 三.泛型分类 1.普通泛型 就是没有设置通配的泛型,泛型表示为某一个类. 声明时: class Test<T>{...} 使用时: Test<Int

JDK5的新特性

本篇博客内容 一.自动装箱和自动拆箱 二.泛型 三.增强for循环 四.静态导入 五.可变参数 六.枚举 一.自动装箱和自动拆箱 二.泛型 三.增强for循环 四.静态导入 五.可变参数 六.枚举 原文地址:https://www.cnblogs.com/xy-ouyang/p/10924512.html

Java基础——集合(三)——泛型、增强for、工具类

         接上篇,<Java基础--集合(二)--迭代器.Map集合> 六.泛型 (1)定义: 泛型是一种把明确类型的工作放在了创建对象或者调用方法时候才去明确的特殊的类型. (2)格式: <数据类型> ArrayList<String> aList=new ArrayList<String>(); <String> 即表示的是泛型 (3)好处:(掌握) A:解决了黄色警告线问题 B:把运行期间的转换异常给提前到了编译期间 C:优化了程序

第三章 C# 泛型

当两个模块功能相似,仅仅只是类型不同的时候,你会怎么办呢.请看以下代码: public class IntClass { List<int> Intlist = new List<int>(); public void AddList(int i) { Intlist.Add(i); } } public void Main() { IntClass c1 = new IntClass(); c1.AddList(1); c1.AddList(1); } 但是当我们想c1.AddL

07.C#泛型的限制和可空类型的简单说明(三章3.5-四章4.1)

自己在写文章的同时,也是在学习,对于书中的语句很多其实没有太好的理解,读一本书,要消化!!!三章都是讲泛型的,最后写一下泛型的限制,对于本章学习的完结,one end,one begin. 看下面的代码 1 public class Teacher 2 { 3 public enum Flag { Chinese, English }; 4 public string Name { get; set; } 5 } 6 7 public class ChineseTeacher : Teacher