Wam
Wam

Reputation: 850

Limited IList<> implementation?

I'm doing some work with stats, and want to refactor the following method :

public static blah(float[] array)
{
    //Do something over array, sum it for example.
}

However, instead of using float[] I'd like to be using some kind of indexed enumerable (to use dynamic loading from disk for very large arrays for example). I had created a simple interface, and wanted to use it.

public interface IArray<T> : IEnumerable<T>
{
    T this[int j] { get; set; }
    int Length { get; }
}

My problem is :

Any help is welcome. Cheers

Upvotes: 1

Views: 832

Answers (3)

Richard
Richard

Reputation: 109080

float[] only inherits IList, not IArray, and AFAIK there's no way to change that.

Array of T also implements IList<T> and others (but these don't always show in tools, several aspects of Array as special cased by the runtime).

I'd like to ditch IArray and only use IList, but my classes would need to implement many methods[...]

This is true, but such implementation is quite quick to do (and should you only need non-modifying operations, you can just throw a NotImplementedException from modifying methods).

In practice in only takes a few minutes to do, and your implementation should be reusable. Also there are types like ReadOnlyCollection<T> to help avoid a lot of this work.

And then my question : how can float[] implement IList whereas it doesn't have these methods ?

A type can explicitly implement interface methods. They are not directly members of the type, but casting to the interface (or reflection) will allow access. This allows a typed collection to implement IEnumerator.Current (returning Object) while also providing a Current property that returns the correct type.

Upvotes: 2

Wam
Wam

Reputation: 850

I ended up writing the following stuff : public class IArrayWrapper : IArray { private float[] innerArray;

    public IArrayWrapper(float[] array)
    {
        innerArray = array;
    }

    public static implicit operator float[](IArrayWrapper wrapper)
    {
        return wrapper.innerArray;
    }

    public static implicit operator IArrayWrapper(float[] array)
    {
        return new IArrayWrapper(array);
    }

    public IEnumerator<float> GetEnumerator()
    {
        return ((IEnumerable<float>) innerArray).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return innerArray.GetEnumerator();
    }

    public float this[int j]
    {
        get { return innerArray[j]; }
        set { innerArray[j] = value; }
    }

    public int Length
    {
        get { return innerArray.Length; }
    }
}

I'm not very proud of it, but I think implicit operators should solve my problem... hopefully.

Upvotes: 0

Anton Gogolev
Anton Gogolev

Reputation: 115779

In fact, float[] array does implement IList<float>:

var floats = new[] { 1.0f, 2.0f, 3.5f };
var list = (IList<float>)floats;

This is per 19.6:

A one-dimensional array S[] implements the interface System.Collections.Generic.IList<S> (IList<S> for short) and its base interfaces. Accordingly, there is an implicit conversion from S[] to IList<S> and its base interfaces.

Upvotes: 1

Related Questions