简体   繁体   English

C#中的协变和反协Monadic类型ala Scala的列表

[英]Covariant and Contravariant Monadic Types ala Scala's List in C#

I'm new to c# but relatively experienced with scala, I'm trying to make a mimic of scala's list class (which is extended by Cons and the static class Nil). 我是C#的新手,但是对Scala经验比较丰富,我正在尝试模仿Scala的列表类(由Cons和静态类Nil扩展)。 I was hoping to get the type behaviour it had as well, since .NET has supported covariance/contravariance since 4.0. 我希望也能获得它的类型行为,因为.NET从4.0开始就支持协方差/相反。 Allow me to show what I mean: 请允许我显示我的意思:

Scala REPL: 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]!!!

In C# this will throw a compiler error because C and B are not the same type with ImmutableList. 在C#中,这将引发编译器错误,因为C和B与ImmutableList的类型不同。

There don't seem to be examples online and I'm still quite the novice with C# so I thought it would be wise to ask if C# could do this in any way before attempting blindingly (I am still trying but I'm also learning the rest of the language first as I go). 在线上似乎没有示例,我仍然是C#的新手,所以我认为在盲目的尝试之前询问C#是否可以以任何方式做到这一点是明智的(我仍在尝试,但我也在学习我会先讲其余语言)。

Thanks! 谢谢!

In C# this will throw a compiler error because C and B are not the same type with ImmutableList. 在C#中,这将引发编译器错误,因为C和B与ImmutableList的类型不同。

In C#, classes are not co/contravariant , these are properties of Interfaces and Delegates used via the in and out keywords. 在C#中, 类不是co / contravariant的 ,它们是通过inout关键字使用的Interfaces和Delegates的属性。 Remember, in C#, a List<T> is a mutable list , and doesn't work like the immutable List[T] in Scala. 记住,在C#中, List<T>是一个可变列表 ,并且不能像Scala中的不可变List[T]一样工作。

What you can do is declare the base type for the 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 { }

Same goes for using an interface for T , but you can't go further than that. 对于T使用接口也是如此,但是您不能做得更多。 This will not compile: 这将无法编译:

void Main()
{
    var bs = new List<B>();
    var cs = new List<C>();
    var result = bs.Concat(cs);
}

For more on that, see Why isn't there generic variance for classes in C# 4.0? 有关更多信息,请参见为什么C#4.0中的类没有通用差异?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM