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?

  • I don't understand, you can't cast List<PolicyVote> to List<Vote<Policy>>, do you mean you create a copy of the list? And C# does support variance: List<PolicyVote> can be cast to IEnumerable<Vote<Policy>> or IReadOnlyList<Vote<Policy>>.
    – svick
    Jan 31, 2016 at 16:38
  • @svick When I say cast, I mean use a loop and cast all the members individually.
    – soandos
    Jan 31, 2016 at 16:39
  • Shouldn't this question be on CodeReview or StackOverflow? Mar 1, 2016 at 17:35

1 Answer 1


I would consider using an interface for Vote instead of generics.

That way if you had something like:

interface IVote {
    // your interface requirements

And then on your class definitions implement the IVote interface:

class PolicyVote : IVote {
    // class def

class FundingVote : IVote { 
    // class def


You could then avoid casting to Vote<T> and use IVote as a type instead and any class that implements IVote will be recognised by the compiler as type safe :

public static int CalculateWinner(List<IVote> votes) {
    // your calc logic

//You can now pass any object that implements `IVote` to the method
//assuming policyVotes and fundingVotes are type List<IVote>
CalculateWinner(policyVotes); // this will work
CalculateWinner(fundingVotes); // so will this 
  • Doesn't this have the same contravariance problem?
    – soandos
    Jan 31, 2016 at 16:40
  • How can I pass in a List<PolicyVote> and have it work?
    – soandos
    Jan 31, 2016 at 19:58
  • @soandos - are you both iterating and modifying the list, or just iterating it? If the latter, you can cast the list to a more general type that doesn't allow mutation, which should then let you cast the contents to a supertype. List is only an issue because it allows both.
    – Jules
    Jan 31, 2016 at 20:51
  • @Jules I am modifying the contents of the list (the individual votes), but not the list of votes itself. So the cast (List<IVote>)(votes) if votes is of type List<PolicyVote> is safe?
    – soandos
    Feb 1, 2016 at 14:49
  • As svick pointed out earlier, you can cast to IEnumerable<superclass> or IReadOnlyList<superclass> from List<subclass>, which should work for you.
    – Jules
    Feb 1, 2016 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.