Обеспечить взаимоисключающие интерфейсы во время компиляции?

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

e.g.:

[InterfaceUsage(MutuallyExclusive = typeof(B))]
interface A {
    //...
}

interface B {
    //...
}

class C : A, B { //should throw an error on compile time
    //...
}

Очевидно, я могу сделать это во время выполнения с отражением, но меня интересует решение во время компиляции.

Я полагаю, что его, вероятно, не существует из коробки, но есть ли способ создать настраиваемый атрибут, который запускается во время компиляции, как это делает AttributeUsage?


person Iain Sproat    schedule 09.05.2011    source источник
comment
Не только с обычным компилятором С#...   -  person Marc Gravell    schedule 09.05.2011
comment
Вы можете создать правило FxCop.   -  person Steven    schedule 09.05.2011
comment
Любопытно понять вариант использования, который требует взаимоисключающих интерфейсов...   -  person Rowland Shaw    schedule 09.05.2011
comment
@Роуленд Шоу, например. ICat и IDog не должны находиться в одном классе. Последующие пользователи моей библиотеки могут не понимать, что их животное не может быть гибридом CatDog, поэтому я хотел бы вставить правило, которое проверяет это для них.   -  person Iain Sproat    schedule 09.05.2011
comment
Можно ли использовать абстрактные классы вместо интерфейсов?   -  person Mike Two    schedule 09.05.2011
comment
@Mike Two - хорошая идея, это сработает в большинстве случаев. К сожалению, у меня есть пара классов, которые уже наследуются от другого класса.   -  person Iain Sproat    schedule 09.05.2011
comment
@sprocketonline - Разве вы не слышали о новом гибриде Собаки-кошки, который родился в лаборатории?   -  person ChaosPandion    schedule 09.05.2011
comment
Я бы подумал о переосмыслении вашей объектной модели, т.е. об использовании композиции вместо наследования. Если что-то не может быть одновременно ICat и IDog, то это не должны быть интерфейсы.   -  person Evan M    schedule 09.05.2011
comment
Скорее всего, вы получите убывающую отдачу от решения времени компиляции. .Net Framework не пытается помешать пользователю сделать нелогичный выбор реализации интерфейса, и вы не должны этого делать! Если это абсолютно необходимо, несколько проверок во время выполнения допустимы, но на самом деле, если пользователь хочет приложить все усилия, чтобы реализовать что-то глупое (например, гипотетические IQueue, IStack и IDictionary все время производные от LinkedList), вы должны наверное пусть.   -  person user7116    schedule 09.05.2011
comment
@sprocketonline Я знаю, что вы подразумеваете под взаимоисключающими - я просто не понимаю вариант использования, который требует этого.   -  person Rowland Shaw    schedule 09.05.2011
comment
Я думаю, что у нас все вместе возникают трудности с пониманием того, почему вы можете захотеть это сделать - есть шанс, что вы можете немного более подробно рассказать о своих фактических интерфейсах, чтобы мы могли понять, почему это не так. имеет смысл для класса реализовать оба?   -  person AakashM    schedule 11.05.2011


Ответы (2)


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

person Steve Wellens    schedule 09.05.2011

Как насчет предоставления им двух методов с одинаковыми сигнатурами, но несовместимыми типами возвращаемых значений?

person Ernest Friedman-Hill    schedule 09.05.2011
comment
Я бы посчитал это скорее предупреждением, поскольку они могут явно реализовать один из интерфейсов. Хотя я почти уверен, что вы не сможете добиться большего успеха без внешнего инструмента. - person ChaosPandion; 09.05.2011