I'm working on a side project, and I turned on all rules for code analysis in Visual Studio, and I got the warning notice:
Warning CA1006 Consider a design where '
Vote<T>.CalculateWinner(List<Vote<T>>)
' doesn't nest generic type 'List<Vote<T>>
'
And it really does point out a sore spot in my design. I have an abstract base class Vote<T>
that contains a list of the options for running an election on type T
.
Here is what I want to exist:
There are three types of objects, PolicyCategory
, Policy
and Funding
. A PolicyCategory
contains a list of votes on the policies within it, and a vote on a Policy
must also contain a list of votes on a Funding
object. The election procedure (happens to be STV) is then run on the votes in the category, and then on the votes on the winning policy. The procedure is the same for both types of votes.
What I have now is PolicyVote : Vote<Policy>
and FundingVote : Vote<Funding>
, the core election logic is in Vote<T>
, and I have methods that cast List<PolicyVote>
to List<Vote<Policy>>
, and then call Vote<T>.CalculateWinner()
.
This is clearly pretty horrible as I'm hacking around the lack of contravariance in C#.
How can this be made better?
Best Answer
I would consider using an interface for Vote instead of generics.
That way if you had something like:
And then on your class definitions implement the
IVote
interface:You could then avoid casting to
Vote<T>
and useIVote
as a type instead and any class that implementsIVote
will be recognised by the compiler as type safe :