общее ограничение NOT, где T:! IEnumerable - PullRequest
44 голосов
/ 04 января 2012

Согласно заголовку, можно ли объявить ограничения на отрицание типов в c # 4?

Ответы [ 6 ]

41 голосов
/ 04 января 2012

Нет - такого понятия нет ни в C #, ни в CLR.

4 голосов
/ 04 января 2012

Насколько я знаю, это невозможно сделать.

То, что вы можете сделать, это некоторая проверка во время выполнения:

public bool MyGenericMethod<T>()
{
    // if (T is IEnumerable) // don't do this

    if (typeof(T).GetInterface("IEnumerable") == null)
        return false;

    // ...

    return true;
}
3 голосов
/ 17 апреля 2017

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

void doIt<T>(IEnumerable<T> what) { }
void doIt<T>(T whats) { }

I исключено следующий код для ссылки на первый метод :

doIt(new List<T>());

Но на самом деле ссылается на второй .

Одним из решений является приведение аргумента следующим образом:

doIt(new List<T>().AsEnumerable<T>());

Приведение может быть скрыто другой перегрузкой:

void doIt<T>(List<T> whats) {
    doIt(whats.AsEnumerable<T>());
}
0 голосов
/ 13 сентября 2016

одно использование для этого будет типом опции.

public class Option<A,B> 
where A : !B
where B : !A
{
    private readonly A a;
    private readonly B b;

    private Option(){}

    public Option(A a) 
    {
        this.a = a
    }

    public Option(B b)  
    {
        this.b = b
    }
} 

проверка во время выполнения, конечно, будет работать, но вы не получите преимущества проверки типа во время компиляции.

0 голосов
/ 04 января 2012

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

Обобщение с ограничением на отрицание типа не имеет никакого смысла, так как нет цели знать отсутствие некоторых свойств / методов , которые вы не хотите использовать .

0 голосов
/ 04 января 2012

Нет, но можно проверить с помощью "is", а затем обработать его соответствующим образом ...

...