C# 中的 Scala 列表中的协变和逆变单子类型
Covariant and Contravariant Monadic Types ala Scala's List in C#
我是 c# 的新手,但对 scala 比较有经验,我正在尝试模仿 scala 的列表 class(由 Cons 和静态 class Nil 扩展)。我也希望获得它的类型行为,因为 .NET 从 4.0 开始就支持 covariance/contravariance。请允许我展示我的意思:
Scala REPL:
class A
class B extends A
class C extends A
val x = new B() :: new B()
//this is type List[B]
val y = new C() :: new C()
//this is type List[C]
val z = new C() :: x
//This uses contravariance to figure out and infer that this is type List[A]!!!
在 C# 中,这将引发编译器错误,因为 C 和 B 与 ImmutableList 的类型不同。
网上似乎没有示例,我仍然是 C# 的新手,所以我认为在盲目尝试之前询问 C# 是否可以以任何方式做到这一点是明智的(我仍在尝试,但我也会先学习其余的语言。
谢谢!
In C# this will throw a compiler error because C and B are not the
same type with ImmutableList.
在 C# 中,类 不是 co/contravariant,这些是通过 in
和 [=13 使用的接口和委托的属性=] 关键字。请记住,在 C# 中,List<T>
是一个 可变列表 ,并且不像 Scala 中的不可变 List[T]
那样工作。
您可以做的是声明 List<T>
:
的基类型
void Main()
{
var list = new List<A>();
list.Add(new B());
list.Add(new C());
}
class A { }
class B : A { }
class C : A { }
使用 T
的接口也是如此,但您不能比这更进一步。这不会编译:
void Main()
{
var bs = new List<B>();
var cs = new List<C>();
var result = bs.Concat(cs);
}
有关详细信息,请参阅 Why isn't there generic variance for classes in C# 4.0?
我是 c# 的新手,但对 scala 比较有经验,我正在尝试模仿 scala 的列表 class(由 Cons 和静态 class Nil 扩展)。我也希望获得它的类型行为,因为 .NET 从 4.0 开始就支持 covariance/contravariance。请允许我展示我的意思:
Scala REPL:
class A
class B extends A
class C extends A
val x = new B() :: new B()
//this is type List[B]
val y = new C() :: new C()
//this is type List[C]
val z = new C() :: x
//This uses contravariance to figure out and infer that this is type List[A]!!!
在 C# 中,这将引发编译器错误,因为 C 和 B 与 ImmutableList 的类型不同。
网上似乎没有示例,我仍然是 C# 的新手,所以我认为在盲目尝试之前询问 C# 是否可以以任何方式做到这一点是明智的(我仍在尝试,但我也会先学习其余的语言。
谢谢!
In C# this will throw a compiler error because C and B are not the same type with ImmutableList.
在 C# 中,类 不是 co/contravariant,这些是通过 in
和 [=13 使用的接口和委托的属性=] 关键字。请记住,在 C# 中,List<T>
是一个 可变列表 ,并且不像 Scala 中的不可变 List[T]
那样工作。
您可以做的是声明 List<T>
:
void Main()
{
var list = new List<A>();
list.Add(new B());
list.Add(new C());
}
class A { }
class B : A { }
class C : A { }
使用 T
的接口也是如此,但您不能比这更进一步。这不会编译:
void Main()
{
var bs = new List<B>();
var cs = new List<C>();
var result = bs.Concat(cs);
}
有关详细信息,请参阅 Why isn't there generic variance for classes in C# 4.0?