Подтвердить что ты не робот

Преобразовать из IList <T> в не-общий IList

Я реализую 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> без повторного заполнения нового списка?

UPDATE:

Объявлена ​​членская переменная _mydata:

private MyData _mydata;

И MyData объявлен:

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

Ответ 1

Почему я могу вернуть List<MyDataRow> из GetList(), но не IList<MyDataRow>

Это потому, что List<T> реализует IList, IList<T> не может быть добавлено к IList, это два отдельных интерфейса. Поэтому, чтобы ответить на ваш вопрос:

Кто-нибудь знает, как мне вернуть IList<MyDataRow> без повторного заполнения нового списка?

Если конкретный тип реализует IList (что делает List<T>), вы можете явно его использовать, например.

return (IList)this.mydata;

Обновление

На основе вашего обновления вам нужно будет обновить MyData, чтобы реализовать IList, иначе у вас нет выбора, кроме как вернуть новую коллекцию, которая ее реализует.

В качестве альтернативы, если MyData действительно является общим списком, я бы предположил, что вы наследуете его от List<T>, таким образом вы получаете гораздо большую гибкость и совместимость из коробки, например.

class MyData : List<MyDataRow>
{
}

Ответ 2

Класс MyData должен реализовать IList вместе с общей версией IList<T>.

class MyData : IList<MyDataRow>, IList
{
}

Ответ 3

IList<T> не распространяется IList, так как неразумно ожидать, что каждая реализация родовой версии предложит тот же контракт, что и не общий. Если бы это расширило IList, кто-то мог бы взять значение, возвращенное из GetList, и разумно ожидать вызова, например. Add(DateTime.Now) или Add(Thread.CurrentThread). Это то, что IList promises.

То, что причина копирования вашего списка в List<T> works - List<T> реализует оба интерфейса и выбрасывает, когда его (явно реализованные) методы IList вызываются с неприемлемыми типами параметров.

Если вы можете уйти с возвратом IEnumerable, сделайте это вместо этого. Если вы можете вернуть IList<MyDataRow> вместо этого, сделайте это. Если вам действительно нужен не-общий IList return, тогда реализуйте интерфейс и обрабатывайте значения не MyDataRow соответствующим образом.

Ответ 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);
}

Ответ 5

Если бы можно было напрямую преобразовать IList<T> в IList, вы могли бы вернуть список, который мог бы (например) быть "заражен" объектами не T через его метод Add(object).