簡體   English   中英

作為方法參數類型的接口可以工作但不能接口列表

[英]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           
}

現在我可以將GroupUser的對象傳遞給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方法工作,以便我可以傳遞UsersGroups的列表?

如果您使用的是.Net 4.0或更高版本,則可以將IList(T)更改為IEnumerable(T),它將起作用。 IList(T)接口的T參數不是協變的,IEnumerable(T)接口的T參數是。 看到

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

進一步解釋。

因為IList<T>不是協變的,這意味着阻止ChangeListGroup添加到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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM