我有一段这样的代码:

public IEnumerable<ICacheMember> Flubvert( IEnumerable<ICacheMember> members )
   {
        // do some stuff to members
        return members;
   }


但是我对为什么不能这样做感到困惑:

public IEnumerable<T> ExecuteFlubversion<T>( IEnumerable<T> memberList ) where T: class,ICacheMember
{
      return Flubvert( memberList );
}


当然,对泛型的约束应该保证memberListICacheMember类型的IEnumerable?我是否真的需要将现有的(但隐式的)ICacheMember对象的集合转换为显式的ICacheMember对象,然后再将其转换回去?我可以理解,给定Flubvert的方法签名,我可能需要将它们转换回去,但是我不明白为什么我必须在方法调用中转换它们。这是我在工作代码中所做的事情,但似乎与泛型的一般优雅行为完全不符,因此我认为我一定会对这种操作方式有所误解。

最佳答案

首先,IEnumerable<out T>(和其他通用类型)的协方差仅在T是引用类型时才有效,因此您需要:

public IEnumerable<ICacheMember> ExecuteFlubversion<T>(IEnumerable<T> memberList)
    where T: class, ICacheMember  // NOTE 'class'
{
    var flub = Flubvert(memberList);   // can you call with 'memberList'?
    return flub;                       // can you return that type?

    // depending on what 'Flubvert' does, maybe return 'IEnumerable<T>'
    // and say:
    // return (IEnumerable<T>)flub;
}


另请注意,我更改了返回值。 C#编译器不能保证从非泛型Flubvert方法返回的对象比IEnumerable<ICacheMember>更具体。

07-27 17:39