Search code examples
c#collections

Convert from System.Collections.Generic.IList<object> to System.Collections.IList


I have implemented the following class:

class LazyList<T> : IList<T>
{
    public LazyList(IEnumerable<T> enumerable) { }
}

I need to use this class with non-generic legacy System.Collections. I have solved half of the problem by using IEnumerable.Cast<object>() as described here https://stackoverflow.com/a/776407/2109230/.

However, I need to cast LazyList<T> to non-generic IList to complete the refactor process. How can I achieve this?

UPDATE 1:

LazyList basically helps me refactor a method that returns IList after iterating an IDataReader. I use data returned from this method to send some updates over WebSocket. The point is to send data constantly, not after processing the entire IDataReader. I have used yield return to return a lazy IEnumerable, but other methods require the refactored method to return IList. So, I came up with the idea of LazyList.

There are actually two methods, one returning IList<T>, which I have refactored successfully, and another returning IList. I wanted to see if there is a simpler way to refactor the version returning IList, without implementing non-generic LazyList. However, I did that and it wasn't that bad.


Solution

  • You should follow the pattern the List<T> does - implement both interfaces and use explicit interface implementations to remove some duplication (see the source code) and limit the exposed contract. Something to get you started:

    class LazyList<T> : IList<T>, IList
    {
        public LazyList(IEnumerable<T> enumerable) { }
      
        public void Add(T item) => throw new NotImplementedException();
        public int Count { get; }
    
        public int Add(object? item)
        {
            Add((T)item!); // call to the generic implementation
            return Count - 1;
        }
    
        int IList.IndexOf(object? item)
        {
            if (IsCompatibleObject(item))
            {
                return IndexOf((T)item!); // call to generic 
            }
            return -1;
        }
    
        public int IndexOf(T item) => throw new NotImplementedException();
        
        private static bool IsCompatibleObject(object? value) => (value is T) || (value == null && default(T) == null);
    
       // ...
    }