Reputation: 850
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 :
Add
, RemoveAt
although they are fixed sizeAny help is welcome. Cheers
Upvotes: 1
Views: 832
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
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
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 interfaceSystem.Collections.Generic.IList<S>
(IList<S>
for short) and its base interfaces. Accordingly, there is an implicit conversion fromS[]
toIList<S>
and its base interfaces.
Upvotes: 1