Анти-ограничение на C # дженерики - PullRequest
3 голосов
/ 15 июля 2010

Вдохновленный Попытка Фила Хаака по объединению нулей или пустых , я пытаюсь написать несколько методов расширения для объекта string, а также для интерфейса IEnumerable<T>, чтобы упростить null или emtpy ckecking. Однако у меня возникают проблемы: когда я пытаюсь вызвать string версию AsNullIsEmpty, компилятор обрабатывает мою строку как IEnumerable<char> и, конечно, выдает неверный тип возврата.

Есть ли какой-нибудь способ наложить «анти-ограничение» на определение версии IEnumerable, чтобы я мог сказать компилятору использовать его, когда тип T равен , а не string? Что-то вроде

public static IEnumerable<T> AsNullIfEmpty(this IEnumerable<T> items)
    where T !: string

Я знаю, что могу просто поменять имя одного из них, но я хочу иметь такое же имя для согласованности.

Обновление: Оказывается, моя проблема с методами расширения была решена другим способом, путем исправления простой и глупой ошибки (я использовал str.IsNullOrEmpty(), метод расширения на IEnumerable<T> вместо string.IsNullOrEmpty(str) ...) но поскольку вопрос об ограничениях на дженерики по-прежнему интересен, я не буду его удалять.

1 Ответ

8 голосов
/ 15 июля 2010

Единственный способ сделать это - создать перегрузку этого расширения, которое принимает string в качестве параметра this.

public static string AsNullIfEmpty(this string value)

Это приведет к тому, что версия с особым типом будет считаться лучшим соответствием перегрузки, чем универсальная версия.

Что касается вашего конкретного вопроса («Могу ли я указать« анти-ограничение »для параметра универсального типа?»), Ответ - нет. Впрочем, можно очень близко подойти с атрибутом Obsolete.

[Obsolete("AsNullIfEmpty is not supported for strings.", true)]
public static string AsNullIfEmpty(this string value)

Это может привести к тому, что компилятор сообщит об ошибке для этой перегрузки.

...