<out T>
和之间有什么区别<T>
?例如:
public interface IExample<out T>
{
...
}
Run Code Online (Sandbox Code Playgroud)
与
public interface IExample<T>
{
...
}
Run Code Online (Sandbox Code Playgroud) 虽然我们可以从基类/接口继承,但为什么我们不能声明List<>
使用相同的类/接口?
interface A
{ }
class B : A
{ }
class C : B
{ }
class Test
{
static void Main(string[] args)
{
A a = new C(); // OK
List<A> listOfA = new List<C>(); // compiler Error
}
}
Run Code Online (Sandbox Code Playgroud)
有办法吗?
来自Joshua Bloch的Effective Java,
协变只是意味着如果X是Y的子类型,那么X []也将是Y []的子类型.数组是协变的因为字符串是Object So的子类型
String[] is subtype of Object[]
不变量仅仅意味着X不是Y的子类型,
List<X> will not be subType of List<Y>.
Run Code Online (Sandbox Code Playgroud)我的问题是为什么决定在Java中使数组协变?还有其他SO帖子,例如为什么阵列不变,但列出协变?,但他们似乎专注于Scala,我无法遵循.
我在理解如何在现实世界中使用协方差和逆变时遇到了一些麻烦.
到目前为止,我见过的唯一例子是同样的旧数组示例.
object[] objectArray = new string[] { "string 1", "string 2" };
Run Code Online (Sandbox Code Playgroud)
很高兴看到一个允许我在开发过程中使用它的例子,如果我能看到它在其他地方使用的话.
继这个问题之后,有人可以在Scala中解释以下内容:
class Slot[+T] (var some: T) {
// DOES NOT COMPILE
// "COVARIANT parameter in CONTRAVARIANT position"
}
Run Code Online (Sandbox Code Playgroud)
我明白之间的区别+T
,并T
在类型声明(它编译如果我使用T
).但是,如何实际编写一个在其类型参数中具有协变性的类而不依赖于创建未参数化的东西?如何确保只能使用实例创建以下内容T
?
class Slot[+T] (var some: Object){
def get() = { some.asInstanceOf[T] }
}
Run Code Online (Sandbox Code Playgroud)
编辑 - 现在得到以下内容:
abstract class _Slot[+T, V <: T] (var some: V) {
def getT() = { some }
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好,但我现在有两个类型参数,我只想要一个.我会再问这个问题:
如何编写一个在其类型中具有协变性的不可变 Slot
类?
编辑2:呃!我用过var
而不是val
.以下是我想要的:
class Slot[+T] (val some: …
Run Code Online (Sandbox Code Playgroud) IEnumerable<T>
是共变体,但它不支持值类型,仅支持引用类型.以下简单代码编译成功:
IEnumerable<string> strList = new List<string>();
IEnumerable<object> objList = strList;
Run Code Online (Sandbox Code Playgroud)
但是从更改string
到int
将得到编译错误:
IEnumerable<int> intList = new List<int>();
IEnumerable<object> objList = intList;
Run Code Online (Sandbox Code Playgroud)
原因在MSDN中解释:
差异仅适用于参考类型; 如果为变量类型参数指定值类型,则该类型参数对于生成的构造类型是不变的.
我搜索过并发现有些问题提到的原因是值类型和引用类型之间的装箱.但它仍然不清楚我的想法为什么拳击是什么原因?
有人可以给出一个简单而详细的解释为什么协方差和逆变不支持值类型以及拳击如何影响这个?
我有一个s()private readonly
列表.我稍后在此列表中添加s并将这些标签添加到以下内容中:LinkLabel
IList<LinkLabel>
LinkLabel
FlowLayoutPanel
foreach(var s in strings)
{
_list.Add(new LinkLabel{Text=s});
}
flPanel.Controls.AddRange(_list.ToArray());
Run Code Online (Sandbox Code Playgroud)
Resharper给我一个警告:Co-variant array conversion from LinkLabel[] to Control[] can cause run-time exception on write operation
.
请帮我弄明白:
我无法理解为什么以下C#代码无法编译.
正如您所看到的,我有一个静态泛型方法Something with a IEnumerable<T>
parameter(并且T
被约束为一个IA
接口),并且此参数不能隐式转换为IEnumerable<IA>
.
解释是什么?(我不寻找解决方法,只是为了解它为什么不起作用).
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
public static class Test
{
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// All those calls are legal
Something2(new List<IA>()); …
Run Code Online (Sandbox Code Playgroud) 今天,我在Java中阅读了一些关于Covariance,Contravariance(和Invariance)的文章.我阅读了英文和德文维基百科的文章,以及IBM的一些其他博客文章和文章.
但我对这些究竟是什么有点困惑?有人说,它是关于类型和子类型之间的关系,也有人说,它是关于类型转换和一些说,它是用来决定一个方法是否重载或超载.
所以我正在用简单的英语寻找一个简单的解释,它向初学者展示了Covariance和Contravariance(和Invariance).加上一点简单的例子.
covariance ×10
c# ×7
c#-4.0 ×3
generics ×3
java ×2
.net ×1
.net-4.0 ×1
arrays ×1
collections ×1
inheritance ×1
list ×1
scala ×1
winforms ×1