19

我正在实现IListSource需要GetList()具有以下签名的方法:

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.

如果我创建一个的 type 列表List<MyDataRow>,填充它并返回这个列表对象,那么它就可以工作了。换句话说,这有效:

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

但是必须重新创建列表才能将其从 typeIList<T>转换为IList. 为什么我可以返回 a List<MyDataRow>' from 'GetList(),但不能返回 a IList<MyDataRow>?有谁知道我在IList<MyDataRow>不重新填充新列表的情况下返回的方法?

更新:

_mydata声明成员变量:

private MyData _mydata;

MyData声明:

public class MyData : IList<MyDataRow>
{
   ....
}
4

5 回答 5

15

为什么我可以返回 a List<MyDataRow>from GetList(),但不能返回IList<MyDataRow>

这是因为List<T>implements不能转换为它们是 2 个独立的接口。所以回答你的问题:IListIList<T>IList

有谁知道我在IList<MyDataRow>不重新填充新列表的情况下返回的方法?

如果具体类型实现IList(实现List<T>),那么您可以显式地转换它,例如

return (IList)this.mydata;

更新

根据您的更新,您必须更新MyData以实现,IList否则您别无选择,只能返回一个实现它的新集合。

或者,如果MyData确实是一个通用列表,那么我建议你让它继承自List<T>,这样你就可以获得更多的灵活性和兼容性,例如

class MyData : List<MyDataRow>
{
}
于 2012-09-19T13:42:29.810 回答
4

该类MyData需要IList与通用版本一起实现IList<T>

class MyData : IList<MyDataRow>, IList
{
}
于 2012-09-19T13:45:47.823 回答
4

IList<T>不扩展IList,因为期望通用版本的每个实现都提供与非通用版本相同的合同是不合理的。如果它确实扩展了IList,那么有人可以获取从返回的值GetList并合理地期望调用,例如Add(DateTime.Now),或Add(Thread.CurrentThread)。这就是IList承诺。

这就是将您的列表复制到List<T>作品的原因 -List<T>实现两个IList接口,并在使用不适当的参数类型调用其(显式实现的)方法时抛出。

如果您可以避免返回IEnumerable,请改为这样做。如果您可以返回IList<MyDataRow>,那就这样做。如果您确实需要非泛型IList返回,请实现接口并MyDataRow适当处理非值。

于 2012-09-19T13:54:17.193 回答
4

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);
}
于 2012-09-19T14:00:34.833 回答
2

如果可以直接将 an 转换IList<T>为 an IList,则可以返回一个列表,该列表可能(例如)通过其方法被非T对象“污染”。Add(object)

于 2012-09-19T13:50:10.537 回答