Как выбросить ошибку компилятора, если более одного элемента имеет тот же атрибут

Простой вопрос, как заставить компилятор С# вызывать ошибку компиляции.


Обновление: может быть, лучше использовать Assert.Fail() вместо этого?

У меня есть настраиваемый атрибут, который должен применяться только к элементу ONE класса. Внутри статического метода моего другого класса он ищет этот один элемент, и я хочу, чтобы он терпел неудачу (не генерировал исключение), если к нему применен более чем один элемент.

public class Foo
{
    [MyCustomAttribute]
    public String FooString { get; set; }

    [MyCustomAttribute]
    public String OtherFooString { get; set; }
}


public class Bar<T>
    where T : class, new()
{
    static Bar()
    {
         //If more than one member of type Foo has MyCustomAttribute
         //applied to it compile error or Assert.Fail()?
    }
}

Ответ 1

Вы можете использовать диагностическую директиву:

#error Oops. This is an error.

или просто предупреждение:

#warning This is just a warning.

Обычно вы хотите поместить их в условные блоки, я бы ожидал...

EDIT: Хорошо, теперь вы обновили свой вопрос, вы просто не можете сделать это во время компиляции. Ваше предложение использовать Assert.Fail помещает проблему во время выполнения.

Я бы посоветовал вам написать единичные тесты, чтобы обнаружить это (перебрать все типы в сборке и проверить, что атрибут был применен не более одного раза для каждого типа).

EDIT: в 2016 году... в то время как анализ кода, предложенный OP, на самом деле не является ошибкой компилятора, теперь, когда Visual Studio использует Roslyn, можно подключиться к компилятору и действительно получить ошибку от компилятора, используя анализатор кода Roslyn. Тем не менее, я по-прежнему лично предпочел бы для этого модульные тесты, так как тогда код мог быть построен и протестирован кем угодно, независимо от того, установлен ли у них анализатор Roslyn. Пока еще нет возможности проверить это с помощью "чисто ванильного" компилятора С#.

Ответ 2

Спустя год после того, как этот вопрос был задан, я понял альтернативное решение для модульных тестов: Анализ кода.

Если не существует правила анализа кода, вы можете даже перевернуть свой собственный. Просто убедитесь, что это правило указано как Ошибка, а не Предупреждение (или обязательно обрабатывайте предупреждения как ошибки). Вот изображение этого экрана:

Code Analysis Error

Конечно, я по-прежнему предпочитаю использовать Unit Test в этом конкретном случае, но я могу определенно увидеть Code Analysis в качестве альтернативного решения, особенно для таких вещей, как пользовательское именование (т.е. все мои классы должны заканчиваться на "Foo", или выбросить ошибку).

Ответ 3

Простой ответ: попросите его скомпилировать что-то синтаксически недействительное.

Ответ 4

Я не считаю, что это может быть сделано, потому что невозможно сообщить компилятору проверить наличие ошибок. Конечно, вы можете использовать #error, как сказал Джон, но нет возможности добавить это условие. Поскольку #error вызывает ошибку каждый раз.

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

Изменить: Черт, вопрос, после того как он был сильно отредактирован.