2012-12-13 11 views
11

Ich habe folgende Erweiterungsmethoden für meine MessageBus:C# Spezialisierung der generischen Erweiterungsmethoden

public static class MessageBusMixins 
{ 
    public static IDisposable Subscribe<T>(
     this IObservable<T> observable, 
     MessageBus bus) 
    where T:class 
    { 
     ... 
    } 

    public static IDisposable Subscribe<T>( 
     this IObservable<Maybe<T>> observable, 
     MessageBus bus) 
    { 
     ... 
    } 
} 

die fein kompiliert. Allerdings, wenn ich versuche, es zu benutzen:

IObservable<Maybe<string>> source = ...; 
MessageBus bus = ...; 

source.Subscribe(bus); 

ich den Fehler, dass keiner der beiden Kandidaten Methoden sind die meisten spezifisch. Aber ich dachte, dass Maybe<T> wäre mehr spezifisch als T oder ist das nicht korrekt?

EDIT

Es wird neugieriger, denn wenn ich die Erweiterung Methode dann explizit aufrufen:

MessageBus.SubscribeTo(source, bus); 

Dann funktioniert es und nimmt die richtige Methode.

+0

Sie können es wie erwartet funktioniert: 'public static IDisposable Abonnieren ( diese IObservable beobachtbar, messagebus Bus), wo T: Vielleicht ' – 2kay

+0

T nicht Vielleicht sind generische Einschränkungen bradgonesurfing

+3

@ 2kay sein kann nicht Teil der Kandidat Auflösung Prozess, so dass es nicht funktioniert – SWeko

Antwort

9

Nun können Sie das Problem beheben, indem die Art Argument spezifiziert wird:

source.Subscribe<string>(bus); 

... als das ist jetzt nur noch das zweite Verfahren anwendbar ist.

Andernfalls wird der Compiler könnte entweder von nennen:

source.Subscribe<string>(bus); 
source.Subscribe<Maybe<string>>(bus); 

Wenn Sie denken, das erste präziser als die zweite ist, werden Sie die Regel in der C# Spezifikation finden müssen, die besagt, so :) Es ist keine unvernünftige Erwartung, aber ich nicht denke, die normalen "mehr spezifischen" Konvertierungen gelten für Typ Parameter sowie regelmäßige Parameter.

So zum Beispiel in Abschnitt 7.5.3.2 der C# 4 spec ("Better Funktion Mitglied") gibt es eine Regel über:

  • Andernfalls, wenn M P spezifischere Parametertypen hat als M Q, dann M P ist besser als M Q. [... viele Details über weniger/mehr ... spezifische]

... aber gibt es keine ähnlichen Punkt über Typparametern. (Das zweite über normale Parameter spricht über Typargumente, aber das ist innerhalb der Parametertypen selbst.)

Eine andere Alternative ist, einfach den Methoden verschiedene Namen zu geben. Haben sie ein subtil unterschiedliches Verhalten? Wenn ja, warum sollte das nicht durch die Namensgebung deutlich gemacht werden? Sie wollen wirklich nicht, dass jemand das falsche Verhalten zeigt, nur weil sie überrascht waren, welche Überladung aufgerufen wurde.

+1

Hallo Jon. Ich habe die Frage mit direktem Aufruf der Erweiterungsmethode aktualisiert, was zu unterschiedlichen Ergebnissen führt. Warum können sich Erweiterungsmethoden nicht spezialisieren, während direkte Aufrufe sind. Passt das zu Ihrem Verständnis des Standards? – bradgonesurfing

+0

In diesem Fall werde ich mit dem direkten Aufruf gehen, da es Kompilierzeit für mich sicher ist. – bradgonesurfing

Verwandte Themen