tags:

views:

154

answers:

3

Hello people,

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 :

  • float[] only inherits IList, not IArray, and AFAIK there's no way to change that.
  • I'd like to ditch IArray and only use IList, but my classes would need to implement many methods like Add, RemoveAt although they are fixed size
  • And then my question : how can float[] implement IList whereas it doesn't have these methods ?

Any help is welcome. Cheers

+1  A: 

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.

Anton Gogolev
I know that, my question is how can it be that it implements IList<float> and ICollection without implementing Add, RemoveAt and these other methods from ICollection/IList ?
Wam
+1  A: 

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.

Richard
think you mean explicit, not implicit
Sekhat
@Sekhat: indeed I did. Corrected.
Richard
Hum, thanks, you learned me the difference between and explicit/implicit interface method implementation.
Wam
A: 

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.

Wam