Ответ 1
Ну, с атрибутами вы всегда можете создать атрибут таким образом, чтобы его функция автоматически не распространялась на типы потомков.
С интерфейсами это невозможно.
Я бы пошел с атрибутами.
У меня есть несколько классов, которые я хочу пометить определенным атрибутом. У меня есть два подхода. Один из них включает использование класса, расширяющего атрибуты. Другой использует пустой интерфейс:
Свойства
public class FoodAttribute : Attribute { }
[Food]
public class Pizza { /* ... */ }
[Food]
public class Pancake { /* ... */ }
if (obj.IsDefined(typeof(FoodAttribute), false)) { /* ... */ }
Интерфейс
public interface IFoodTag { }
public class Pizza : IFoodTag { /* ... */ }
public class Pancake : IFoodTag { /* ... */ }
if (obj is IFoodTag) { /* ... */ }
Я не решаюсь использовать атрибуты из-за использования Reflection. В то же время, однако, я не решаюсь создать пустой интерфейс, который действительно служит только тегом. Я тестировал стресс, и разница во времени между ними составляет всего около трех миллисекунд, поэтому производительность здесь не поставлена.
Ну, с атрибутами вы всегда можете создать атрибут таким образом, чтобы его функция автоматически не распространялась на типы потомков.
С интерфейсами это невозможно.
Я бы пошел с атрибутами.
Я должен сказать иначе. Я думаю, что для вашего примера интерфейс маркера имеет больше смысла.
Это потому, что кажется, что однажды вы можете добавить некоторые члены в IFood
.
Ваш дизайн начинается следующим образом:
interface IFood {}
Но тогда вы решили добавить что-то там:
interface IFood {
int Calories { get; }
}
Существуют также другие способы для расширения интерфейсов:
static class FoodExtensions {
public static void Lighten(this IFood self) {
self.Calories /= 2;
}
}
Вероятно, вы сами ответили на свой вопрос. Атрибуты здесь более логичны, отражение не БОЛЬШОЙ МОНСТР С КРАСНЫМИ ГЛАЗАМИ =)
btw, можете ли вы показать код вызова, где вы определяете отмеченные с помощью типов интерфейсов? Разве вы не используете там отражение?
В этом случае, как вы говорите, вы не используете интерфейс правильно.
Что не так с использованием отражения, которое вы получаете? Обычный ответ - это производительность, но, как правило, это практически не проблема почти во всех случаях.