C#通用多态性[重复]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#通用多态性[重复]相关的知识,希望对你有一定的参考价值。

这个问题在这里已有答案:

假设有一个像这样的基类叫做Cup

public abstract class Cup { }

让我们假设继承PaperCup和继承Cup类的PlasticCupPaperCup

public class PlasticCup : PaperCup { }
public class PaperCup : Cup { }

并假设Main类中有两种方法。

static void Test01 (PaperCup cup) { }
static void Test02 (Cup cup) { }

TEST1

PaperCup A = new PaperCup();
Test01(A);
Test02(A);

以上代码工作正常。 A实例可以传递给那两个函数,因为它是PaperCup本身并且它继承了Cup基类。

TEST2

PlasticCup B = new PlasticCup();
Test01(B);
Test02(B);

上面的代码仍然正常。 B实例也可以被函数采用,虽然它是PlasticCup但它继承PaperCup并且它最终来自Cup

但是泛型!!

我们来看看以下方法。

static void Test010 (IList<PaperCup> cup) { }
static void Test011(IList<PlasticCup> cup) { }
static void Test012(IList<Cup> cup) { }

以下试验将在两次方法调用中失败。

IList<PlasticCup> BB = new List<PlasticCup>();
Test010(BB); // Fail CS1503 Compiler Error
Test011(BB);
Test012(BB); // Fail CS1503 Compiler Error

简单的问题

为什么在使用Generic时将派生类型传递给这些函数是不可能的?是不是应该工作,因为C#是一种OOP语言?

答案

好的,想象一下允许以下内容:

IList<Cup> plasticCups = new List<PlasticCup>();

那么以下是可能的:

plasticCups.Add(new PaperCup()); //ouch!

而你刚刚在一个塑料杯列表中插入了一个纸杯。这似乎不对。

你问的是generic type varianceIList<T>T中是不变的,因为任何其他选项(协变或逆变)都是不安全的。

C#允许接口和委托中的泛型类型差异,但只有在编译器可以确保其安全时才允许。

例如IEnumerable<out T>T中是协变的,因为你不能将纸杯插入IEnumerable<PlasticCup>(规则实际上是类型T从未用作方法参数),所以以下是完全安全的并且将编译:

IEnumerable<Cup> plasticCups = Enumerable.Empty<PlasticCup>();

值得注意的是,由于C#诞生时“支持其他现有语言特性”的原因,数组也支持类型差异,但它完全被破坏了。使用数组这是完全合法的:

object[] strings = new string[] { .... }
strings[0] = new object(); //oh oh

而且你会得到一个不幸的运行时异常。使用泛型这不可能发生。

以上是关于C#通用多态性[重复]的主要内容,如果未能解决你的问题,请参考以下文章

java 代码片段

游戏类的 Objective C 多态性

Eclipse 中的通用代码片段或模板

C/C++编程笔记:C++中的函数重载和浮动

SSR技术原理是啥?

多态的好处??