Как сделать безопасное приведение, используя дженерики в C #? - PullRequest
1 голос
/ 31 марта 2010

Я хочу реализовать универсальный метод для универсального класса, который позволил бы безопасно приводить, см. Пример:

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 в методе, поскольку оно не определено в методе. Но как я могу указать обратное ограничение?

Ответы [ 2 ]

17 голосов
/ 31 марта 2010

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 голосов
/ 31 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...