views:

160

answers:

2

I am writing a C# wrapper for a 3rd party library that reads both single values and arrays from a hardware device, but always returns an object[] array even for one value. This requires repeated calls to object[0] when I'd like the end user to be able to use generics to receive either an array or single value.

I want to use generics so the callee can use the wrapper in the following ways:

MyWrapper<float> mw = new MyWrapper<float>( ... );
float value = mw.Value; //should return float;

MyWrapper<float[]> mw = new MyWrapper<float[]>( ... );
float[] values = mw.Value; //should return float[];

In MyWrapper I have the Value property currently as the following:

public T Value
{
   get
   {
      if(_wrappedObject.Values.Length > 1)
         return (T)_wrappedObject.Value; //T could be float[]. this doesn't compile.
      else
         return (T)_wrappedObject.Values[0]; //T could be float. this compiles.
   }
}

I get a compile error in the first case:

Cannot convert type 'object[]' to 'T'

If I change MyWrapper.Value to T[] I receive:

Cannot convert type 'object[]' to 'T[]'

Any ideas of how to achieve my goal? Thanks!

+2  A: 

You need to trick the compiler by casting your array into an object first

public T Value
{
   get
   {
      if(_wrappedObject.Values.Length > 1)
         return (T)(object)_wrappedObject.Value; //T could be float[]. this doesn't compile.
      else
         return (T)_wrappedObject.Values[0]; //T could be float. this compiles.
   }
}
joegtp
This compiles, however remember that T is an array itself in these circumstances. So (T)(object)_wrappedObject.Value throws and exception "Unable to cast object of type 'System.Object[]' to type 'System.Single[]'" when T is a float[]
bufferz
+1  A: 

Edit: Updated answer. The library is returning an object array, you will not be able to simply return it as T, be it an array or a single element, without doing some work with it. The function below is an example of taking an array of objects and either returning it as an array or a single element.

public static T GetValue<T>(object[] inputs)
{
    if (typeof(T).IsArray)
    {
        Type elementType = typeof(T).GetElementType();
        Array array = Array.CreateInstance(elementType, inputs.Length);
        inputs.CopyTo(array, 0);
        T obj = (T)(object)array;
        return obj;
    }
    else
    {
        return (T)inputs[0];
        // will throw on 0-length array, check for length == 0 and return default(T)
        // if do not want exception
    }
}

Example of consuming it:

object[] inputs = { 1f, 2f, 3f }; // what the library is returning
float[] array = GetValue<float[]>(inputs); // what you want?
float singleValue = GetValue<float>(inputs); // what you want?
Anthony Pegram
Remember that T is itself an array in these circumstances, i.e. T[] would represent an array of arrays. So I still need to return just T not T[]. I hope that makes sense. Thanks for the help!
bufferz
The original code intended for T to an element type, not an array type. Based on T, you would get an array of T. However, I have updated the code with a function that will determine if T is an array and act accordingly.
Anthony Pegram
This did exactly what I was looking for! Thanks so much Anthony!!!!
bufferz