2012-12-13 22 views
11

Mam następujące metody rozszerzenie dla mojego MessageBus:C# specjalizacji ogólnych metod rozszerzenie

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) 
    { 
     ... 
    } 
} 

który kompiluje grzywny. Jednak gdy próbuję go użyć:

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

source.Subscribe(bus); 

pojawia się błąd, że żadna z tych dwóch metod kandydujących są najbardziej konkretne. Jednak myślałem, że Maybe<T> będzie więcej specyficzne niż T lub czy to nie jest poprawne?

EDIT

Robi Curiouser bo gdybym wywołać metodę rozszerzenia wyraźnie następnie:

MessageBus.SubscribeTo(source, bus); 

Wtedy to działa i wybiera właściwą metodę.

+0

Można zrobić to działa zgodnie z oczekiwaniami: 'public static IDisposable Subskrybuj ( to IObservable obserwowalne, messagebus autobus) gdzie T: Może ' – 2kay

+0

T nie może być Może bradgonesurfing

+3

@ 2kay Generic ograniczenia nie są częścią proces rozstrzygania kandydatów, więc to nie zadziała – SWeko

Odpowiedz

9

Cóż, można go naprawić poprzez określenie typu argumentu:

source.Subscribe<string>(bus); 

... jak to jest teraz tylko druga metoda ma zastosowanie.

przeciwnym razie kompilator mógł zadzwonić albo od:

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

Jeśli uważasz, że pierwszy jest bardziej szczegółowy niż sekundę, będziesz musiał znaleźć regułę w specyfikacji C#, który mówi tak :) To nie jest to nieuzasadnione oczekiwanie, ale domyślne "bardziej szczegółowe" konwersje mają zastosowanie do parametrów typu , a także do zwykłych parametrów.

Tak na przykład w punkcie 7.5.3.2 w C# 4 spec ("Better Function Member") istnieje przepis o:

  • W przeciwnym razie, jeśli M P ma więcej niż konkretne typy parametrów M Q, następnie M P jest lepsza niż M Q. [... dużo szczegółów o mniej/bardziej konkretnych ...]

... ale nie ma podobny punkt o parametrach typu. (Drugi o normalnych parametrach mówi o argumentach typu, ale to jest w samych typach parametrów.)

Inną alternatywą jest po prostu nadać metodom różne nazwy. Czy mają subtelnie inne zachowanie? Jeśli tak, dlaczego nie uczynisz tego naprawdę oczywistego przez nazywanie? Naprawdę nie chcesz, aby ktoś źle się zachowywał, tylko dlatego, że był zaskoczony, że wywołano przeciążenie.

+1

Cześć Jon. Zaktualizowałem to pytanie, bezpośrednio wywołując metodę rozszerzenia, która daje inne wyniki. Dlaczego metody rozszerzeń nie są w stanie specjalizować się, podczas gdy połączenia bezpośrednie są. Czy to pasuje do twojego zrozumienia standardu. – bradgonesurfing

+0

W tym przypadku przejdę do bezpośredniego połączenia, ponieważ jest to dla mnie bezpieczna kompilacja. – bradgonesurfing

Powiązane problemy