Skip to main content

Generics for reducing redundancies

I have a routine that can be potentially reduced.

internal ArrayBufferObject GetAccessorArray()
{
    ColladaDocument colladaDocument = GetColladaDocument();
    ColladaArray colladaArray = colladaDocument.GetSpecialElement<ColladaArray>(Source);
    ArrayBufferObject bufferObject;

    if (IsSimpleParamsConfiguration() == false)
        throw new NotSupportedException("complex accessor params not supported");

    string simpleParamsType = Params[0].Type;

    if (simpleParamsType == ArrayTypeFloat) {
        uint cursorOffset = Offset;

        ArrayBufferObject<float> arrayBufferObject = new ArrayBufferObject<float>(BufferObject.Hint.StaticCpuDraw);

        for (uint i = 0; i < Count; i++) {
            foreach (ColladaParam param in Params) {
                if (param.Name != null)
                    arrayBufferObject[cursorOffset - Offset] = (float) colladaArray[cursorOffset];
                cursorOffset++;
            }
            cursorOffset += Stride - (uint)Params.Count;
        }

        bufferObject = arrayBufferObject;

    } else if (simpleParamsType == ArrayTypeInt) {
        uint cursorOffset = Offset;

        ArrayBufferObject<int> arrayBufferObject = new ArrayBufferObject<int>(BufferObject.Hint.StaticCpuDraw);

        for (uint i = 0; i < Count; i++) {
            foreach (ColladaParam param in Params) {
                if (param.Name != null)
                    arrayBufferObject[cursorOffset - Offset] = (int) colladaArray[cursorOffset];
                cursorOffset++;
            }
            cursorOffset += Stride - (uint)Params.Count;
        }

        bufferObject = arrayBufferObject;
    } else
        throw new NotSupportedException(String.Format("simple accessor params type {0} not supported", simpleParamsType));

    return (bufferObject);
}

As you can see, there are two if branches that are the same. Essentially they create a generic class using float and int type.

The class ArrayBufferObject is the base of ArrayBufferObject<T>, but only the latter implements an indexer (strongly typed). It is implemented as following:

public T this[uint index]
{
    get
    {
        if ((MemoryBuffer == null) || (MemoryBuffer.AlignedBuffer == IntPtr.Zero))
            throw new InvalidOperationException("not defined");
        if (index >= ItemCount)
            throw new ArgumentException("index out of bounds", "index");

        return ((T) Marshal.PtrToStructure(new IntPtr(MemoryBuffer.AlignedBuffer.ToInt64() + (index * mItemSize)), typeof(T)));
    }
    set
    {
        if ((MemoryBuffer == null) || (MemoryBuffer.AlignedBuffer == IntPtr.Zero))
            throw new InvalidOperationException("not defined");
        if (index >= ItemCount)
            throw new ArgumentException("index out of bounds", "index");

        Marshal.StructureToPtr(value, new IntPtr(MemoryBuffer.AlignedBuffer.ToInt64() + (index * mItemSize)), false);
    }
}

The source of the assigned item comes from a ColladaArray class, that is an abstract class wrapping an array of values. To resolve the data accessor I've defined in it a generic numeric accessor like the following:

/// <summary>
/// Access this array.
/// </summary>
/// <param name="i">
/// The index of the element to be accessed.
/// </param>
/// <returns>
/// It returns an equivalent <see cref="System.Double"/> of the value accessed.
/// </returns>
public virtual double this[uint i] { get { throw new NotSupportedException("array accessor not implemented"); } }

Which is implemented in each derived class returning the real array value casted to double (all arrays contains numeric data... hopefully).


How would you suggest to remove the GetAccessorArray routine redundancies? Help! Soon it will grow up with all possible numeric types!

Luca
  • 204
  • 1
  • 7