开发者

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

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)' get开发者_JAVA技巧s 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.


    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.


    The Updater function can only handle objects of type CommodityVO.

    If this is a base type of various types you want to be able to pass to Updater, add a where constraint. where T : CommodityVO


    This should work

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

    You want to constrain the generic type T to a type your Updater function actually accepts.

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新问答

    问答排行榜