But in this case IDE says me that Type parameter T is never used
In most cases, it is indeed very weird to declare a generic type and then not use it.
However, there is a potentially meaningful reason here.
Suppose you have a single class that, for some reason, indexes both likes and comments (this is not always a violation of SRP, though it does seem that way in this simplified example)
With your non-generic example, you'd run into an issue:
public class CommentsAndLikesIndexer : IIndexer
{
public void FillIndex()
{
Console.WriteLine("index filled!");
}
}
var myIndexer = new CommentsAndLikesIndexer();
There's no way to signal that this can be used for the indexing of both comments and likes. There's also no way to only index comments (or likes) if both are implemented (other than some unintuitive boolean properties that go outside of the interface itself).
There is also no way to figure out what myIndexer
is capable of indexing.
When you use a generic interface, you can specify which entities can be indexed:
public class CommentsAndLikesIndexer : IIndexer<Comment>, IIndexer<Like>
{
public void FillIndex()
{
Console.WriteLine("index filled!");
}
}
var myIndexer = new CommentsAndLikesIndexer();
Now, we have a way of testing what can be indexed by myIndexer
:
bool isLikeIndexer = myIndexer is IIndexer<Like>;
bool isCommentIndexer = myIndexer is IIndexer<Comment>;
However, we still run into the issue where FillIndex()
will be used for both cases.
Maybe that's what you want. But let's assume that you want them to be separate. You can achieve this by using explicit interface declarations:
public class CommentsAndLikesIndexer : IIndexer<Comment>, IIndexer<Like>
{
public void IIndexer<Comment>.FillIndex()
{
Console.WriteLine("comment index filled!");
}
public void IIndexer<Like>.FillIndex()
{
Console.WriteLine("like index filled!");
}
}
And now we have separate implementations for a doubly implemented interface!
Some sidenotes:
- The downside is that when an interface is explicitly implemented, you must always use the interface as the variable's type, to clarify which method you want to use.
CommentsAndLikesIndexer myIndexer = new CommentsAndLikesIndexer(); myIndexer.FillIndex();
does not work. The compiler doens't know which method you want.
IIndexer<Comment> myIndexer = new CommentsAndLikesIndexer(); myIndexer.FillIndex();
does work.
- By extension,
CommentsAndLikesIndexer myIndexer = new CommentsAndLikesIndexer(); (myIndexer as IIndexer<Comment>).FillIndex();
would also work.
- If your method signature would be unique based on the generic parameter (e.g.
void FillIndex(T myObj)
), then you could do this without explicit interface implementation, since the two methods will not conflict.
Is it OK to use generics in cases like this (for type distinguish only)?
The above being said, a generic interface that doesn't use its generic type parameter is an unusual thing to see. There are fringe use cases for it, but I would strongly suggest doublechecking if this is the best approach for you.
If your method is indeed correct as it is intended (no input parameters), then this can be a valid approach.
void DoSomething()
black holes of type erased side-effect