Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 接口作为方法参数类型起作用,但不是接口列表_C#_Interface - Fatal编程技术网

C# 接口作为方法参数类型起作用,但不是接口列表

C# 接口作为方法参数类型起作用,但不是接口列表,c#,interface,C#,Interface,我有一个接口和两个继承该接口的类,如下所示 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 i

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

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           
}
错误是

cannot convert from List<User> to List<ILeader>
无法从一个列表转换到另一个列表

如何使我的
ChangeList
方法起作用,以便我可以传递
用户列表和
组列表?

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


进一步解释。

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

public void ChangeList<T>(IList<T> leaderList) where T : ILeader
{
  //do some thing           
}
public void变更列表(IList leaderList),其中T:ILeader
{
//做点什么
}
现在您可以传递这两个列表。

在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.
//列表实现协变接口
//我数不清。但是类是不变的。
列表=新列表();//这里有编译器错误。
为了实现这一点,您需要将
用户
强制转换为
ILeader
。您可以使用
userList.Cast()

执行此操作,因为
IList
是不协变的,这意味着在
用户列表中添加
,这显然是无效的,
更改列表
无法停止

要传递两种类型的列表,请将列表转换为
列表

如果
ChangeList
添加了除
User
s以外的任何项目,则转换将失败。您的最佳选择是仅从结果中获取
用户
s:

var leaderList = userList.Cast<ILeader>().ToList();
ChangeList(leaderList);  
userList = leaderList.OfType<User>().ToList();  // will ignore anything that's not a `User`
var leaderList=userList.Cast().ToList();
变更列表(领导列表);
userList=leaderList.OfType().ToList();//将忽略任何不是“用户”的内容`

您可能无法执行,这取决于您想对
变更列表执行的操作。
ChangeList
的作用是什么?@DStanley:对列表项进行一些过滤,并为列表中的少数项重置Name属性可能与“谢谢”重复。如果我想从我的方法返回更新的列表,我是否应该使用IEnumerable作为返回类型,并将其转换回我调用此方法的任何位置的列表或列表?@Happy,IEnumerable是只读的,因此您不能使用此方法添加/删除项。但是,您可以修改项目本身(例如更改其名称属性)。因此,您不需要返回“结果列表”,因为原始列表没有更改。+1谢谢。我希望我的changelist方法对列表中某些用户的Name属性值进行更改并将其返回。我的返回类型应该是什么。从技术上讲,您不需要,因为列表只是对底层对象的引用,但是最好返回一个
IList
,而不使用传入的列表。大多数“change”方法不会在传入的引用中更改,而是返回一个新实例。OK。因此,在调用该方法时,我应该使用
作为列表强制转换它?不,不能将其强制转换为列表-必须使用上面的方法进行转换
ChangeList(userList.Cast<ILeader>().ToList()); 
var leaderList = userList.Cast<ILeader>().ToList();
ChangeList(leaderList);  
userList = leaderList.Cast<User>().ToList();
var leaderList = userList.Cast<ILeader>().ToList();
ChangeList(leaderList);  
userList = leaderList.OfType<User>().ToList();  // will ignore anything that's not a `User`