It's already been covered in a few topics that empty interfaces that are used as markers where identification occurs at run time are code smell, but what about when you have something like this:
public interface IPropertyRetriever<out T>
{
public string Name { get; }
public T Retrieve();
}
public interface IComparablePropertyRetriever<out T> : IPropertyRetriever<T> where T : IComparable
{
}
In this example, although IComparablePropertyRetriever<T>
is an empty interface, it does add a constraint to what T
can be. Would something like this also be considered code smell?
EDIT
Ok so here is both how I'm using it and the use case.
I'm building an expression parser that consists of an expression, an operator and a constant, so I ended up with this:
public interface IOperator<out T>
{
public IPropertyRetriever<T> LeftObjectRetriever { get; }
public T RightObject { get; }
public bool Compare();
}
T
can only ever be one of 4 types: string
, bool?
, long?
and Version
My operators are things like StartsWith
, GreaterThan
, LowerEquals
, Contains
...
Clearly some operators such as StartsWith
and Contains
only work on strings and that's pretty simple to do, I can just do this:
public class BeginsWith : IOperator<string>
{
public BeginsWith(IPropertyRetriever<string> leftObjectRetriever, string rightObject)
{
LeftObjectRetriever = leftObjectRetriever;
RightObject = rightObject;
}
public IPropertyRetriever<string> LeftObjectRetriever { get; }
public string RightObject { get; }
public bool Compare()
{
throw new System.NotImplementedException();
}
}
But others, such as LowerThan
work on all other types, except string. And although I guess I could do something like this (which is ultimately what the IComparablePropertyRetriever<T>
interface is doing)
public class LowerThan : IOperator<IComparable>
{
}
It still allows me to pass a string
to LowerThan
since string implements IComparable
By shifting the responsability to the classes implementing IPropertyRetriever
(which I can control far more easily) I can instead do something like this:
public class FileVersionRetriever : IComparablePropertyRetriever<Version>
{
}
And implement LowerThan
as follows:
public interface IComparableOperator : IOperator<IComparable>
{
public new IComparablePropertyRetriever<IComparable> LeftObjectRetriever { get; }
}
public class LowerThan : IComparableOperator
{
}
And I guess now that I've explained that the whole question turned into something completely different which is how to implement this better xD