[英]Interface as method parameter type works but not List of Interface
我有一個接口和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
}
現在我可以將Group
或User
的對象傳遞給Change方法,它可以工作。 但是當我嘗試使用List
to ChangeList
方法執行相同操作時,它會給出編譯時錯誤。
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
的列表?
如果您使用的是.Net 4.0或更高版本,則可以將IList(T)更改為IEnumerable(T),它將起作用。 IList(T)接口的T參數不是協變的,IEnumerable(T)接口的T參數是。 看到
http://msdn.microsoft.com/en-us/library/dd469487.aspx
進一步解釋。
因為IList<T>
不是協變的,這意味着阻止ChangeList
將Group
添加到Users
列表沒有任何意義,這顯然是無效的。
要傳遞兩種類型的列表,請將列表轉換為List<ILeader>
:
ChangeList(userList.Cast<ILeader>().ToList());
但是要知道,這實際上並不投列表,它會創建一個新的列表,其中每個成員都是實例ILeader
。 這意味着ChangeList可以將一個Group
添加到列表中,這意味着您無法將其轉換回List<User>
。
如果ChangeList
沒有向列表中添加任何成員,您只需將其轉換回來:
var leaderList = userList.Cast<ILeader>().ToList();
ChangeList(leaderList);
userList = leaderList.Cast<User>().ToList();
如果ChangeList
添加除User
的任何項目,則轉換將失敗。 您最好的選擇是僅從結果中獲取User
:
var leaderList = userList.Cast<ILeader>().ToList();
ChangeList(leaderList);
userList = leaderList.OfType<User>().ToList(); // will ignore anything that's not a `User`
實際上,您應該依賴於第二種方法的泛型類型約束:
public void ChangeList<T>(IList<T> leaderList) where T : ILeader
{
//do some thing
}
現在您可以傳遞兩個列表。
在C#中,類不是covarient,這是您在此處嘗試使用的功能。 有關詳細信息,請參閱此常見問題解答 。
需要記住的幾條重要規則:
此功能僅適用於通用接口和委托。 如果實現變體通用接口,則實現類仍然是不變的。 類和結構不支持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>()
執行此操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.