Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# specialization of generic extension methods

I have the following extension methods for my MessageBus:

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

which compiles fine. However when I try to use it:

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

source.Subscribe(bus);

I get the error that neither of the two candidate methods are most specific. However I thought that Maybe<T> would be more specific than T or is that not correct?

EDIT

It gets curiouser because if I call the extension method explicitly then:

MessageBus.SubscribeTo(source, bus);

Then it works and picks the correct method.

like image 338
bradgonesurfing Avatar asked Dec 13 '12 08:12

bradgonesurfing


1 Answers

Well, you can fix it by specifying the type argument:

source.Subscribe<string>(bus);

... as that's now only the second method is applicable.

Otherwise, the compiler could call either of:

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

If you think the first is more specific than the second, you'll have to find the rule in the C# specification which says so :) It's not an unreasonable expectation, but I don't think the normal "more specific" conversions apply to type parameters as well as regular parameters.

So for example, in section 7.5.3.2 of the C# 4 spec ("Better Function Member") there a rule about:

  • Otherwise if MP has more specific parameter types than MQ, then MP is better than MQ. [... lots of details about less/more specific ...]

... but there's no similar point about type parameters. (The second about normal parameters talks about type arguments, but that's within the parameter types themselves.)

Another alternative is to simply give the methods different names. Do they have subtly different behaviour? If so, why not make that really obvious via the naming? You really don't want someone to get the wrong behaviour just because they were surprised about which overload was called.

like image 199
Jon Skeet Avatar answered Sep 28 '22 05:09

Jon Skeet