2009-06-22 6 views

Antwort

19

Konvertierungsoperatoren können nicht generisch sein. Aus dem spec Abschnitt 10.10, hier ist das Format einer Umwandlung betreiber declarator:

conversion-operator-declarator: 
    implicit operator type ( type identifier ) 
    explicit operator type ( type identifier )

Vergleichen Sie dies mit, sagen wir, ein Verfahren-Header:

Methode-header : Attribute opt Methode-Modifikatoren opt Teil opt Rückgabetyp Mitglied-name Typ-Parameter-Liste opt ( formal-Parameter-Liste opt) Typ-Parameter-Einschränkungsklauseln opt

(Sorry über die Formatierung - nicht sicher, wie es zu tun Wette ter.)

Beachten Sie, dass das Operatorformat keine Typ-Parameterliste oder Typ-Parameterbeschränkungen enthält.

+2

Und selbst wenn wir benutzerdefinierte generische Konvertierungen unterstützen würden, wäre dies immer noch illegal. Es ist nicht erlaubt, eine Konvertierung zu definieren, die eine integrierte Konvertierung ersetzt. Dies wäre der Fall, wenn T und U vom selben Typ wären; Sie würden die Identitätskonvertierung ersetzen. –

+1

Da Umwandlungen vom Compiler entschieden werden, wenn T und U vom selben Typ sind, würde es nicht die benutzerdefinierte Umwandlung verwenden und leagal sein. –

2

Ihr Code läuft darauf hinaus, die Zeile: return new Foo<U>((U)a.Item)

Wo Sie versuchen, eine Basisklasse zuzuordnen eine vererbte Klasse, die unmöglich ist.

Sagen wir T (Basisklasse) vom Typ ist Stream und U ist vom Typ MemoryStream (geerbt Klasse), Sie können keine Stream auf eine Variable vom Typ MemoryStream zuweisen.

+0

Sicher kannst du, Wenn die Referenz das Objekt als Stream maskiert, aber es ist tatsächlich ein MemoryStream, dann können Sie es sicherlich in einen Memory Stream umwandeln. Dies ist eine legitime Methode, das Problem ist, dass Sie keine generischen Constraints für eine Operatorüberladung festlegen können ... – LaserJesus

+0

... Wenn Sie den Code, den ich habe, als eine Methode anstelle einer Operatorüberladung ausdrücken, wird er kompiliert – LaserJesus

0

Es sieht zu sein wie Sie eine kontra Umwandlung wollen, aber struct s sind unveränderlich, die Umwandlung kauft dir nichts, du kannst einfach new Foo<U>((U)a.Item) sagen, wie @Gidon darauf hingewiesen hat.

Wenn Sie als Foo zu ändern, um eine Klasse zu sein, dann können wir einen Unterschied machen:

public interface IFoo<in T> { 
    T Item { 
     set; 
    } 
} 

public class Foo<T>:IFoo<T> { 
    public Foo(T item) { 
     this.Item=item; 
    } 

    public T Item { 
     get; set; 
    } 

    // public static explicit operator Foo<U>(U a) { 
    // return new Foo<U>((U)a.Item); 
    // } 
} 

und verwenden Sie es mögen:

var foo = new Foo<object>(new object { }); 
IFoo<String> bar = foo; 
bar.Item="123"; 
var b = Object.ReferenceEquals(foo, bar); // true 

By the way, Varianz in generische Schnittstellen ist nur verfügbar von .netfx 4.0.

Verwandte Themen