如果我们将其用于接口,那么为什么不为类提供它呢?使用时会出现什么问题?
假设您有一个C<T>在T中是协变的类。它的实现是什么样的?T只能外出。这意味着C<T>不能有任何采用T的方法,带有setter的T类型的任何属性 或T类型的任何字段 ,因为在逻辑上,字段与属性setter相同。T进去了。
C<T>
就T而言,用协变类构建的唯一有用的东西几乎是不变的。现在,我认为拥有协变不可变列表和堆栈以及类似的类类型真是太棒了。但是,该功能并不是那么出色,以致于显然可以证明使类型系统本机支持协变不可变类类型的大量支出是合理的。
上面的评论要求提供一个在何处有用的示例。考虑以下草图:
sealed class Stack<out T> { private readonly T head; private readonly Stack<T> tail; public T Peek() { return head; } public Stack<T> Pop() { return tail; } public Stack(T head, Stack<T> tail) { this.tail = tail; this.head = head; } } static class StackExtensions { public static Stack<T> Push<T>(this Stack<T> tail, T head) { return new Stack<T>(head, tail); } public static bool IsEmpty<T>(this Stack<T> stack) { return stack == null; } }
假设您有协变类。现在你可以说
Stack<string> strings = null; strings = strings.Push("hello"); strings = strings.Push("goodbye"); Stack<object> objects = strings; objects = objects.Push(123);
嘿,我们只是将一个整数压入了一个字符串堆栈,但是一切顺利!没有理由为什么它不是类型安全的。违反可变数据结构上类型安全性的操作可以在不可变数据结构上安全协变。