Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics: T not assignable to known type. (Why wont this compile?)

Tags:

c#

generics

I've recently tried to simplify some of my code by using generics where possible. However, this particular example has me stumped... Yet it looks so innocent!

Here's the offending code (simplified).

public static void Updater(CommodityVO vo)
{
    // Update something
}

public static void BulkUpdate<T>(IEnumerable<T> vos)
{
    foreach (var vo in vos)
    {
        Updater(vo);
    }
}

In Visual Studio, the 'vo' in 'Updater(vo)' gets a squiggly line and the compiler (VS2010) reports:

Argument type 'T' is not assignable to parameter type CommodityVO

  • It doesn't seem to matter what the type of 'vo' is. eg: string doesn't work either.
  • List<T> behaves the same as IEnumerable<T>
  • Various 'where' clauses seemed to have no effect.
  • I have worked around this issue for now. But I'd like to know why this was rejected... Especially since it all looks fine to me. What am I missing?

    All help appreciated.

    like image 253
    lerenau Avatar asked Mar 02 '11 22:03

    lerenau


    1 Answers

    What you're looking for here is a generic constraint. The type T needs to be constrained to be an instance of CommodityVO

    public static void BulkUpdate<T>(IEnumerable<T> vos) where T : CommodityVO {
      foreach (var vo in vos) {
        Updater(vo);
      }
    }
    

    Without this generic constraint the C# compiler has no information on the generic parameter T and must assume the worst case that T is instantiated as object. The type object is not compatible with CommodityVO and hence it issues an error. By adding the constraint you are limiting the values T can be instantiated as to CommodityVO or types deriving from CommodityVO which means the conversion to CommodityVO is legal and hence allowed.

    like image 149
    JaredPar Avatar answered Oct 13 '22 00:10

    JaredPar