One of the rules in Microsoft’s FxCop static code analysis tool suggests that you should avoid empty interfaces. From MSDN:
Interfaces define members that provide a behavior or usage contract. The functionality that is described by the interface can be adopted by any type, regardless of where the type appears in the inheritance hierarchy. A type implements an interface by providing implementations for the members of the interface. An empty interface does not define any members. Therefore, it does not define a contract that can be implemented.
If your design includes empty interfaces that types are expected to implement, you are probably using an interface as a marker or a way to identify a group of types. If this identification will occur at run time, the correct way to accomplish this is to use a custom attribute. Use the presence or absence of the attribute, or the properties of the attribute, to identify the target types. If the identification must occur at compile time, then it is acceptable to use an empty interface.
I’m going to call this rule out as fundamentally wrong. There are many scenarios both at compile time and at runtime where determining that an instance implements a marker interface is of great value. To suggest that using an attribute is the “correct” way to make identifications at runtime is a sweeping statement that cannot be supported. Further there is a reliance here that the exceptions will be considered when evaluating the rule. Unfortunately it is all too common (and I myself have been guilty of this) of taking the tool pronouncement without question and these details will be lost. As a result designs that are entirely valid solutions will be degraded for no good reason.
There seems to be an assumption in the above that the contract of an interface is only that which is explicitly specified in terms of its members. This assumption is clearly false. Almost every possible interface has implicit contracts that are not directly expressed in the code. For instance the IDisposable.Dispose() method has an implicit contract that it will not throw if invoked multiple times (not that Microsoft themselves always follow this contract). This contract is not expressed directly on the interface as C# provides no way to do so. Yet it exists. I see no legitimate reason to deny that the contract of an interface may be entirely implicit provided it is done in a considered fashion.
It is entirely legitimate that at runtime I may wish to test if an instance adheres to a contract implicitly defined by an interface. This could be done with an attribute but dealing with attributes is inherently more complex. Further attributes cannot be considered compile time in constructs such as generics. If I wish to make decisions at both compile time and runtime or even to not unnecessarily close off the possibility a marker interface is the only possible choice. If I chose an attribute and later wish to do compile time checking them I would need to perform a significant refactoring (which may not be possible if my API has already been published).
Attributes of course do have usages that interfaces (marker or otherwise) do not. An interface cannot be used at anything but the type level, attributes may be attached to almost anything. Attributes may also carry usage specific data and provide behaviour. If you need these capabilities then your choice is clear. Personally I find APIs that require these usages to be on the whole difficult and obscure to work with an extend (with some notable exceptions such as parameterised tests in MbUnit). However they are useful (if overused) capabilities that are worth considering.
In summary: FxCop is wrong, Marker Interfaces rock. Go forth and disable rule CA1040 immediately.