2012-09-19 79 views
17

我實現IListSource,需要一個方法GetList()具有以下特徵:自IList <T>轉換到非通用的IList

IList GetList() 

我使用.NET框架2,我想返回一個對象,執行IList如下:

public System.Collections.IList GetList() 
{ 
    return this._mydata; // Implements IList<MyDataRow>    
} 

但我得到一個編譯錯誤說:Cannot implicitly convert type MyData to System.Collections.IList

如果我創建一個新的類型的列表List<MyDataRow>,填充它並返回此列表對象,然後它的工作。因此,換句話說,這個工程:

public System.Collections.IList GetList() 
{ 
    List<MyDataRow> list = new List<MyDataRow>(); 
    foreach (MyDataRow row in this._mydata) 
    { 
     list.Add(row); 
    } 
    return list; 
} 

但它似乎非常低效的必須重新創建列表只是爲了IList<T>類型得到它的IList。爲什麼我可以退回List<MyDataRow>' from 'GetList(),但不是IList<MyDataRow>?有沒有人知道有一種方法可以讓我返回IList<MyDataRow>而無需重新填充新列表?

UPDATE:

_mydata成員變量聲明:

private MyData _mydata; 

而且MyData聲明:

public class MyData : IList<MyDataRow> 
{ 
    .... 
} 
+0

什麼是'_mydata'場聲明的類型? –

+1

@NicoleCalinoiu:根據他得到的錯誤信息,它是'MyData'。 – Heinzi

回答

14

爲什麼我可以一個List<MyDataRow>GetList()返回,但不是IList<MyDataRow>

這是因爲List<T>實現IListIList<T>不能轉換到IList它們是2個獨立的接口。所以要回答你的問題:

有沒有人知道一種方式讓我返回IList<MyDataRow>沒有重新填充新列表?

如果具體類型實現IList(其中List<T>做),那麼你可以明確地投它例如

return (IList)this.mydata; 

更新

根據您的更新,你將不得不更新MyData實施IList否則你別無選擇,只能返回一個新的集合,其實現它。

另外,如果MyData確實是一個通用的清單,然後我會建議你把它從List<T>繼承,這樣你會得到更多的靈活性&兼容性開箱例如

class MyData : List<MyDataRow> 
{ 
} 
+0

這確實解釋了這個問題,但沒有提供解決方案:myData的類型爲IList ,他仍然需要調用.ToList(),他想避免這種情況。 –

+0

@Baboon如果'myData'的類型是'IList ',但具體類型是'List ',那麼明確的轉換就是所有需要的。 – James

+1

謝謝詹姆斯的詳細解答。我會給你信用的,因爲從列表繼承的建議,而不是像我在做的那樣在列表中封裝List 成員,這確實是我的問題的最簡單的解決方案。謝謝您的幫助。 – BruceHill

4

MyData類需要實現IList與通用版本IList<T>一起。

class MyData : IList<MyDataRow>, IList 
{ 
} 
+0

+1。我冒昧地修復了課程名稱。 (根據OP的錯誤消息,類本身是MyData,而不是MyDataRow)。 – Heinzi

+0

謝謝,那麼它也有效:) – Xharze

2

如果有可能到IList<T>直接轉換成IList,你可以返回,可能(例如)可以通過其Add(object)方法「污染」與非T對象的列表。

+0

你的第二段已經到了它的關鍵,但第一個似乎有點關閉 - 編譯錯誤恰好是因爲'IList '不是從'IList'派生的。 – shambulator

+0

優秀點。相應修改,並感謝修正。你是絕對正確的。 –

3

IList<T>不延伸IList,因爲期望每個通用版本的實現都提供與非通用版本相同的合同是不合理的。如果它確實延伸IList,則某人可以從GetList中獲得返回的值併合理地期望例如呼叫Add(DateTime.Now)Add(Thread.CurrentThread)。這就是IList的承諾。

這是複製列表到List<T>作品的原因 - List<T>實現接口,並拋出時,其(顯式實現)IList方法被稱爲與不適當的參數類型。

如果您可以在返回IEnumerable時離開,請改爲執行此操作。如果您可以返回IList<MyDataRow>,那就這樣做。如果您確實需要非通用IList返回,則實現該接口並適當地處理非MyDataRow值。

+0

+1指出實施IList與IList 的危險' –

3

無論您的數據集合類實現IList或創建一個適配器,它封裝IList<T>並實現IList

public sealed class NonGenericList<T> : IList 
{ 
    private readonly IList<T> _wrappedList; 

    public NonGenericList(IList<T> wrappedList) 
    { 
     if(wrappedList == null) throw new ArgumentNullException("wrappedList"); 

     _wrappedList = wrappedList; 
    } 

    public int Add(object value) 
    { 
     _wrappedList.Add((T)value); 
     return _wrappedList.Count - 1; 
    } 

    public void Clear() 
    { 
     _wrappedList.Clear(); 
    } 

    public bool Contains(object value) 
    { 
     return _wrappedList.Contains((T)value); 
    } 

    public int IndexOf(object value) 
    { 
     return _wrappedList.IndexOf((T)value); 
    } 

    public void Insert(int index, object value) 
    { 
     _wrappedList.Insert(index, (T)value); 
    } 

    public bool IsFixedSize 
    { 
     get { return false; } 
    } 

    public bool IsReadOnly 
    { 
     get { return _wrappedList.IsReadOnly; } 
    } 

    public void Remove(object value) 
    { 
     _wrappedList.Remove((T)value); 
    } 

    public void RemoveAt(int index) 
    { 
     _wrappedList.RemoveAt(index); 
    } 

    public object this[int index] 
    { 
     get { return _wrappedList[index]; } 
     set { _wrappedList[index] = (T)value; } 
    } 

    public void CopyTo(Array array, int index) 
    { 
     _wrappedList.CopyTo((T[])array, index); 
    } 

    public int Count 
    { 
     get { return _wrappedList.Count; } 
    } 

    public bool IsSynchronized 
    { 
     get { return false; } 
    } 

    public object SyncRoot 
    { 
     get { return this; } 
    } 

    public IEnumerator GetEnumerator() 
    { 
     return _wrappedList.GetEnumerator(); 
    } 
} 

用法:

public System.Collections.IList GetList() 
{ 
    return new NonGenericList<MyDataRow>(this._mydata); 
} 
相關問題