2014-10-07 2 views
1

Эта проблема очень сложна для объяснения, поэтому я высмеивал какой-то фиктивный код, чтобы показать проблему, с которой я столкнулся. Это связано с общими ограничениями на методы расширения. В моем методе расширения мне нужен общий класс (но пример этого не показывает). Давайте углубимся в:Почему универсальное ограничение интерфейса испортило использование методов расширения?

У меня есть два интерфейса:

public interface IOne { } 

public interface ITwo { } 

Теперь я создаю некоторые методы расширения для них:

public static class Extensions 
{ 
    public static string ParseValue(this ITwo ob) 
    { 
     return "Two"; 
    } 

    public static string ParseValue<T>(this T obj) where T : class, IOne 
    { 
     return "One"; 
    } 
} 

выглядит хорошо, верно? Теперь я создаю реализацию ITwo, и это будет запутаться:

public class Two: ITwo 
{ 
    public string Test() 
    { 
     return this.ParseValue(); 
    } 
} 

Этого класс не компилируется. Я получаю следующую ошибку:

The type 'GenericProblem.Two' cannot be used as type parameter 'T' in the generic type or method 'GenericProblem.Extensions.ParseValue(T)'. There is no implicit reference conversion from 'GenericProblem.Two' to 'GenericProblem.IOne'.

Как решить эту проблему?

+0

См. Мой ответ [здесь] (http://stackoverflow.com/questions/23217585/generic-extension-method-resolution-fails). Думаю, это дубликат, не так ли? –

+0

@SriramSakthivel, не уверен, вы получили то же сообщение об ошибке? –

+0

Из связанного вопроса: * Тип «System.Collections.Generic.List » не может использоваться как параметр типа «T» в родовом типе или методе.* –

ответ

2

Для ошибки, у меня answered it here.

How can I solve this problem?

Вы должны бросить this, как ITwo типа перед вызовом ParseValue, в противном случае компилятор не сможет выбрать правильный матч.

public class Two : ITwo 
{ 
    public string Test() 
    { 
     return ((ITwo)this).ParseValue(); 
    } 
} 
+0

Да, это работает! Но даже после прочтения ответа я все еще озадачен тем, почему компилятор не может понять это ... –

+1

@ KeesC.Bakker Я объяснил это довольно хорошо в связанном ответе, в какой части вы его не понимаете? В частности, в этой части я объяснил, почему это не работает. * Проблема (угадывание) проверка общих ограничений происходит после того, как компилятор выбирает более близкую перегрузку. Это делает недействительной выбранную лучшую перегрузку в этом случае. * –

+0

Я знаю ... но я думаю, что эту проблему можно было бы легко решить компилятором. Потому что он знает, что это не правильный метод. Я попытаюсь поиграть с пространством имен. Это может привести меня куда-то, поскольку эти интерфейсы живут в своих собственных пространствах имен. –

0

Кажется довольно прямолинейным для меня.

В классе расширения:

public static class Extensions 
{ 
    public static string ParseValue(this ITwo ob) 
    { 
     return "Two"; 
    } 

    public static string ParseValue<T>(this T obj) where T : class, IOne 
    { 
     return "One"; 
    } 
} 

У вас есть метод, ParseValue<T> и вы помещаете ограничение на него, говоря, что T должен быть типа IOne

В вашей реализации ITWO, вы попробуйте вызвать метод расширения на объекте this. Очевидное this имеет тип ITwo, поэтому ваш метод расширения больше не будет работать.

Просто измените подпись вашего метода расширения как:

public static string ParseValue<T>(this T obj) where T : class, ITwo 

Это должно сделать трюк.

Edit:

Согласно первоначальному спрашивающего, решение не компилировать. Ниже находится полный исходный код, как я есть, и это скомпилировать:

public interface IOne { } 

public interface ITwo { } 

public static class Extensions 
{ 
    public static string ParseValue(this ITwo ob) 
    { 
     return "Two"; 
    } 

    public static string ParseValue<T>(this T obj) where T : class, ITwo 
    { 
     return "One"; 
    } 
} 

public class Two : ITwo 
{ 
    public string Test() 
    { 
     return this.ParseValue(); 
    } 
} 
+0

Извините, но я тогда не совсем понимаю. Возможно, отредактируйте свой вопрос с более конкретным примером, и я посмотрю, что я могу сделать. – Complexity

+0

жаль, что я не понял решения. Я попробовал, но это тоже не скомпилировано. Я получаю: Тип «GenericProblem.Extensions» уже определяет член, называемый «ParseValue», с теми же типами параметров. –

+0

@ KeesC.Bakker См. Мой обновленный ответ. Я предоставил код и могу гарантировать, что это скомпилируется. Просто протестирован на моей машине. – Complexity

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