2017-02-06 3 views
10

Предположим, что я определил два несвязанных типа и два метода расширения с той же подписью, но разные фильтры типа:C# общий метод разрешения терпит неудачу с неоднозначной ошибки вызова

public class Foo {} 
public class Bar {} 

public static class FooExtensions 
{ 
    public static TFoo Frob<TFoo>(this TFoo foo) where TFoo : Foo { } 
    public static TFoo Brob<TFoo>(this TFoo foo) where TFoo : Foo { } 
} 

public static class BarExtensions 
{ 
    public static TBar Frob<TBar>(this TBar bar) where TBar : Bar { } 
} 

Тогда, когда я пишу new Foo().Frob(); я получаю ошибку

error CS0121: The call is ambiguous between the following methods or properties: 'FooExtensions.Frob<TFoo>(TFoo)' and 'BarExtensions.Frob<TBar>(TBar)'

Может кто-нибудь объяснить, почему это не удается, и как ее избежать?

EDIT: Это происходит в VS2015 Update 3 и VS2017 RC.

EDIT2: Идея заключается в том, чтобы иметь свободно API, который работает по иерархии классов:

new Foo() 
    .Frob() 
    .Brob() 
+0

Принимаемый ответ правильный; Я отмечаю, что то, что вы здесь делаете, - это плохая практика. Не используйте методы расширения, которые расширяют * все *, либо расширяя объект, либо расширяя общий тип T. Почти всегда есть лучший дизайн. В этом случае, почему бы просто не расширить Foo и Bar? Какая неотразимая польза для создания этих общих? –

+0

@EricLippert, я довольно упростил сценарий. В действительности методы расширения возвращают 'TFoo'. Идея здесь состоит в том, чтобы свободно использовать методы API, которые работают с иерархией классов. Поэтому я мог бы написать 'new Foo(). Frob() .Grob() .Bobob();'. Проблема возникает, когда у меня есть два независимых типа, но с методами расширения, принимающими аналогичные аргументы в том же порядке. –

ответ

11

Ограничение параметра универсального типа не является частью сигнатуры метода. Эти два метода по существу одинаковы с точки зрения разрешения; когда компилятор пытается разрешить вызов, он видит два допустимых метода и не имеет возможности выбрать лучший, поэтому вызов помечен как неоднозначный.

Вы можете узнать больше об этой проблеме here.

+0

Спасибо за ссылку; не мог бы сказать это лучше. –

+3

@EricLippert Большое вам спасибо, трудно переоценить, насколько я узнал об этом языке, и программирование в целом, чтение вашего блога. – InBetween

Смежные вопросы