当T可以是一个数组时,C#泛型

时间:2010-04-21 14:47:51

标签: c# generics templates

我正在为第三方库编写一个C#包装器,它从硬件设备读取单个值和数组,但总是返回一个object []数组,即使是一个值也是如此。当我希望最终用户能够使用泛型来接收数组或单个值时,这需要重复调​​用object [0]。

我想使用泛型,因此被调用者可以通过以下方式使用包装器:

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[];

在MyWrapper中,我目前的Value属性如下:

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.
   }
}

我在第一种情况下遇到编译错误:

  

无法转换类型   'object []'到'T'

如果我将MyWrapper.Value更改为T [],我会收到:

  

无法转换类型   'object []'到'T []'

有关如何实现目标的任何想法?谢谢!

2 个答案:

答案 0 :(得分:10)

修改:更新回答。该库正在返回一个对象数组,您将无法简单地将其作为T返回,无论是数组还是单个元素,而无需使用它。下面的函数是一个获取对象数组并将其作为数组或单个元素返回的示例。

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
    }
}

消费它的例子:

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?

答案 1 :(得分:3)

您需要先通过将数组转换为对象来欺骗编译器

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.
   }
}