5

我有一个接口和 2 个继承该接口的类,如下所示

public interface ILeader
{
    int ID { set; get; }
    string Name { set; get; }
}
public class User : ILeader
{
    public int ID { set; get; }
    public string Name { set; get; }
}
public class Group : ILeader
{
    public int ID { set; get; }
    public string Name { set; get; }
}

现在我有 2 个方法,它有一个类型的参数ILeader和 ILeader 的 IList

public void Change(ILeader leader)
{
  //do some thing           
}
public void ChangeList(IList<ILeader> leaderList)
{
  //do some thing           
}

现在我可以将一个对象传递GroupUserChange 方法并且它可以工作。但是当我尝试用ListtoChangeList方法做同样的事情时,它给了我编译时错误。

IList<User> userList=new List<User>();
userList.Add(new User { ID=1, Name ="Happy"});

Change(userList[0]);  //this works

ChangeList(userList);  //this throws compile error

错误是

cannot convert from List<User> to List<ILeader>

如何使我的ChangeList方法起作用,以便我可以同时传递 和 的Users列表Groups

4

4 回答 4

6

如果您使用的是 .Net 4.0 或更高版本,您可以将您的 IList(T) 更改为 IEnumerable(T) 并且它会起作用。IList(T) 接口的 T 参数不是协变的,而 IEnumerable(T) 接口的 T 参数是协变的。看

http://msdn.microsoft.com/en-us/library/dd469487.aspx

进一步解释。

于 2012-11-02T18:50:33.167 回答
5

因为IList<T>不是协变的,这意味着没有什么可以停止ChangeList将 a 添加Group到 的列表中Users,这显然是无效的。

要传递这两种类型的列表,请将列表转换为 a List<ILeader>

ChangeList(userList.Cast<ILeader>().ToList()); 

但是请注意,这实际上并没有强制转换列表,它会创建一个列表,其中每个成员都是ILeader. 这意味着 ChangeList 可以将 a 添加Group到列表中,这意味着您无法将其转换回List<User>.

如果ChangeList没有将任何成员添加到列表中,您可以将其转换回来:

var leaderList = userList.Cast<ILeader>().ToList();
ChangeList(leaderList);  
userList = leaderList.Cast<User>().ToList();

如果ChangeList 添加s以外的任何项目,User则转换将失败。您最好的选择是从结果中Users:

var leaderList = userList.Cast<ILeader>().ToList();
ChangeList(leaderList);  
userList = leaderList.OfType<User>().ToList();  // will ignore anything that's not a `User`
于 2012-11-02T18:51:12.420 回答
3

您实际上应该在第二种方法上依赖泛型类型约束:

public void ChangeList<T>(IList<T> leaderList) where T : ILeader
{
  //do some thing           
}

现在您可以通过这两个列表。

于 2012-11-02T18:50:54.040 回答
2

在 C# 中,类不是协变的,这是您在此处尝试使用的功能。有关更多信息, 请参阅此常见问题解答。

要记住的几个重要规则:

此功能仅适用于通用接口和委托。如果你实现一个变体泛型接口,实现类仍然是不变的。C# 4.0 中的类和结构不支持变体。因此以下内容无法编译:

// List<T> implements the covariant interface
// IEnumerable<out T>. But classes are invariant.
List<Person> list = new List<Employee>(); // Compiler error here.

为了完成这项工作,您需要将您的文件User转换为ILeader. 你会用userList.Cast<ILeader>().

于 2012-11-02T18:50:57.037 回答