HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Generics for reducing redundancies

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
reducingredundanciesforgenerics

Problem

I have a routine that can be potentially reduced.

internal ArrayBufferObject GetAccessorArray()
{
    ColladaDocument colladaDocument = GetColladaDocument();
    ColladaArray colladaArray = colladaDocument.GetSpecialElement(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 arrayBufferObject = new ArrayBufferObject(BufferObject.Hint.StaticCpuDraw);

        for (uint i = 0; i  arrayBufferObject = new ArrayBufferObject(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, 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 * mIte

Solution

Presumably you could pull those sections out into a generic method.

private ArrayBufferObject CreateArrayBuffer(ColladaArray colladaArray)
{
     uint cursorOffset = Offset;

     ArrayBufferObject arrayBufferObject = new ArrayBufferObject(BufferObject.Hint.StaticCpuDraw);

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

     return arrayBufferObject;
}


And then replace those sections with a call to that method.

if (simpleParamsType == ArrayTypeFloat)
    return CreateArrayBuffer(colladaArray);
else if (simpleParamsType == ArrayTypeInt)
    return CreateArrayBuffer(colladaArray);
else
    throw new NotSupportedException(String.Format("simple accessor params type {0} not supported", simpleParamsType));


Depending on the types that you're converting to and from, the call to Convert.ChangeType() may have to be changed to something else, but it should be sufficient for the standard numeric types. For more information on type conversion, see this.

Code Snippets

private ArrayBufferObject CreateArrayBuffer<T>(ColladaArray colladaArray)
{
     uint cursorOffset = Offset;

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

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

     return arrayBufferObject;
}
if (simpleParamsType == ArrayTypeFloat)
    return CreateArrayBuffer<float>(colladaArray);
else if (simpleParamsType == ArrayTypeInt)
    return CreateArrayBuffer<int>(colladaArray);
else
    throw new NotSupportedException(String.Format("simple accessor params type {0} not supported", simpleParamsType));

Context

StackExchange Code Review Q#8008, answer score: 4

Revisions (0)

No revisions yet.