2016-05-05 11 views
2

Ich bin neu in C#, aber relativ erfahren mit scala, ich versuche, die Listenklasse von scala nachzuahmen (die um Cons und die statische Klasse Nil erweitert wird). Ich hatte gehofft, das Typ-Verhalten auch zu bekommen, da .NET Kovarianz/Kontravarianz seit 4.0 unterstützt. Erlauben Sie mir, zu zeigen, was ich meine:Kovariante und kontravariante monadische Typen ala Scalas Liste in C#

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# wird dies einen Compiler-Fehler werfen, weil C und B mit ImmutableList nicht vom gleichen Typ sind.

Es scheinen keine Beispiele online zu sein und ich bin immer noch ziemlich Anfänger mit C#, also dachte ich, es wäre klug zu fragen, ob C# das irgendwie kann, bevor ich blendend versuche (ich versuche es immer noch, aber ich Ich lerne auch zuerst den Rest der Sprache, während ich gehe.

Danke!

+0

Dies scheint, wie Sie Typinferenz wollen, wenn eine Liste erstellen. C# hat das nicht. – juharr

+0

Sie haben Recht, der Gedanke war mir in den Sinn gekommen, aber C# hat das mit dem Schlüsselwort "var", und ich weiß, dass es auch eine Möglichkeit gibt, Typ-Annotationen manuell zu analysieren (die zur Laufzeit in .NET gehalten werden) ?) und finde den kleinsten gemeinsamen Vorfahren in der Typhierarchie (das ist eher hässlich). –

+0

Ich möchte nur die Prepend/Append-Operation in der Lage sein, diese Art Inferenz zu tun ... gibt es einen Weg? –

Antwort

3

In C# wird dies einen Compiler Fehler werfen, weil C und B nicht die gleichen Typ mit ImmutableList sind.

In C# Klassen sind nicht co/kontra, sind diese Eigenschaften von Schnittstellen und Delegierten über die in und out Schlüsselwörter verwendet. Denken Sie daran, in C# ist eine List<T> eine veränderbare Liste und funktioniert nicht wie die unveränderliche List[T] in Scala.

Was Sie tun können, ist den Basistyp für die List<T> erklären:

void Main() 
{ 
    var list = new List<A>(); 
    list.Add(new B()); 
    list.Add(new C()); 
} 

class A { } 
class B : A { } 
class C : A { } 

Das Gleiche gilt für T eine Schnittstelle für die Verwendung, aber man kann nicht weiter gehen als das. Dies kompiliert nicht:

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

Für mehr dazu finden Sie Why isn't there generic variance for classes in C# 4.0?