Interfaces or Attributes for Tagging Classes?

Viewed 3749

I have a couple of classes that I wish to tag with a particular attribute. I have two approaches in mind. One involves using an Attribute-extending class. The other uses an empty interface:

Attributes

public class FoodAttribute : Attribute { }

[Food]
public class Pizza { /* ... */ }

[Food]
public class Pancake { /* ... */ }

if (obj.IsDefined(typeof(FoodAttribute), false)) { /* ... */ }

Interface

public interface IFoodTag { }

public class Pizza : IFoodTag { /* ... */ }
public class Pancake : IFoodTag { /* ... */ }

if (obj is IFoodTag) { /* ... */ }

I'm hesitant to use the attributes due to its usage of Reflection. At the same time, however, I'm hesitant on creating an empty interface that is only really serving as a tag. I've stress-tested both and the time difference between the two is only about three milliseconds, so performance is not at stake here.

5 Answers

Well, with attributes, you can always create the attribute in such a way that its function doesn't propagate to descendant types automatically.

With interfaces, that's not possible.

I would go with attributes.

You probably have answered on you question by your own. Attributes is more logical here, reflection is not a BIG MONSTER WITH RED EYES =)

btw, can you show calling code, where you determine marked with interface types? Aren't you using reflection there?

It's an old question, but maybe someone stumbles on it like I did. Seems in this case:

"If the object is Food, I would return FoodEventArguments. If the object were, say, Beverage, I'd return DrinkEventArguments. Basically, there's a common base class (let's say ConcessionStandItem) that gets passed into the function"

tagging with either interface or attribute and then checking with an if statement is not the only option you have.

Might be a valid scenario for the visitor pattern with implementations for each 'ConcessionStandItem' like FoodEventArguments CreateEventArgs(Pizza pizza).... as well.

Maybe food for thought for someone else in this scenario. (pun intended).

In this case, as you say, you're not using an interface correctly.

What's wrong with using reflection the get you attributes? The usual answer is performance but that is generally not a real issue in nearly all cases.

Related