1

Я хочу реализовать универсальный метод на универсальный класс, который позволил бы бросить безопасно, смотрите пример:Как сделать безопасный листинг с использованием дженериков в C#?

public class Foo<T> : IEnumerable<T> 
{ 
    ... 
    public IEnumerable<R> SafeCast<R>() 
     where T : R 
    { 
     return this.Select(item => (R)item); 
    } 
} 

Однако компилятор говорит мне, что Foo<T>.SafeCast<R>() does not define parameter 'T'. Я понимаю это сообщение, что не могу указать ограничение на T в методе, так как оно не определено в методе. Но как я могу указать обратное ограничение?

+0

Какое поведение вы ожидаете, если T не является производным от R? – Jake

+1

@ Jake: намерение здесь состоит в том, что если R не выбрано так, что T можно конвертировать в R, то программа не скомпилируется. Например, у вас может быть Foo f и скажем f.SafeCast . Если вы сказали f.SafeCast , то это не скомпилировалось. К сожалению, мы не поддерживаем эту функцию. –

ответ

17

C# не имеет такого ограничения. Ограничение должно иметь форму «R должно быть конвертируемым - X"; мы не поддерживаем ограничений формы «R должен быть конвертируемым от X».

К сожалению, это облегчает определенные сценарии, связанные с контравариантными преобразованиями.

Scala допускает такое ограничение, кстати.

Интересно, что вы можете делать то, что вы хотите с помощью метода расширения, но вы тогда должны быть избыточными, когда вы называете его:

public static IEnumerable<R> SafeCast<T, R>(this IEnumerable<T> x) where T : R 
{ 
    return x.Cast<R>(); 
} 

Теперь вы можете сказать:

IEnumerable<Giraffe> giraffes = whatever; 
IEnumerable<Animal> animals = giraffes.SafeCast<Giraffe, Animal>(); 

В C# 4 ваш код будет в значительной степени ненужным; IEnumerable<T> безопасно ковариантно в T в C# 4 , если T является ссылочным типом.

0

public IEnumerable<R> SafeCast<T,R>() where T : R - это подпись, я думаю, вам нужно это сделать. Разве это не делает то, что вы хотите?

+3

Нет, это redeclares T. OP хочет внешний T. –

+2

Ahh, я вижу. Не удалит мой ответ, чтобы люди могли узнать из вашего комментария и почему мое предложение НЕ является решением. :-) – Jaxidian

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