从IList <t>转换为非通用IList </t>

时间:2012-09-19 13:36:26

标签: c# .net list generics c#-2.0

我正在实施IListSource,要求方法GetList()具有以下签名:

IList GetList()

我正在使用.NET framework 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>

更新:

声明_mydata成员变量:

private MyData _mydata;

宣布MyData

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

5 个答案:

答案 0 :(得分:15)

  

为什么我可以从List<MyDataRow>返回GetList(),而不是IList<MyDataRow>

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

  

有没有人知道如何在不重新填充新列表的情况下返回IList<MyDataRow>

如果具体类型实现IListList<T>执行),那么您可以明确地转换它,例如

return (IList)this.mydata;

<强>更新

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

或者,如果MyData确实是通用列表,那么我建议您继承List<T>,这样您就可以获得更多的灵活性。开箱即用的兼容性,例如

class MyData : List<MyDataRow>
{
}

答案 1 :(得分:4)

MyData课程需要实施IList以及通用版本IList<T>

class MyData : IList<MyDataRow>, IList
{
}

答案 2 :(得分:4)

IList<T>不会延伸IList,因为期望通用版本的每个实现都提供与非通用版本相同的合同是不合理的。如果确实延长了IList,则有人可以获取GetList返回的值并合理地预期会调用,例如Add(DateTime.Now)Add(Thread.CurrentThread)。那是IList所承诺的。

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

如果您可以退回IList,请改为执行此操作。如果您可以返回IEnumerable,那就去做吧。如果您确实需要非泛型IList<MyDataRow>返回,请实现该接口并适当处理非IList值。

答案 3 :(得分: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);
}

答案 4 :(得分:2)

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