Обобщения C #, когда T может быть массивом - PullRequest
14 голосов
/ 21 апреля 2010

Я пишу оболочку C # для сторонней библиотеки, которая читает как отдельные значения, так и массивы с аппаратного устройства, но всегда возвращает массив 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 []' to 'T []'

Есть идеи, как достичь моей цели? Спасибо!

Ответы [ 2 ]

11 голосов
/ 21 апреля 2010

Редактировать: Обновленный ответ .Библиотека возвращает массив объектов, вы не сможете просто вернуть его как 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?
3 голосов
/ 21 апреля 2010

Вам нужно обмануть компилятор, сначала приведя ваш массив к объекту

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.
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...