2010-04-21 12 views
10

Ich schreibe einen C# -Wrapper für eine 3rd-Party-Bibliothek, die einzelne Werte und Arrays von einem Hardwaregerät liest, aber immer ein Objekt [] -Array sogar für einen Wert zurückgibt. Dies erfordert wiederholte Aufrufe von Objekt [0], wenn der Endbenutzer in der Lage sein soll, Generika zu verwenden, um entweder ein Array oder einen einzelnen Wert zu erhalten.C# Generics, wenn T ein Array sein könnte

Ich möchte Generika verwenden, damit der Angerufene den Wrapper auf folgende Weise verwenden:

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 ich die Value-Eigenschaft haben zur Zeit wie folgt:

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

ich bekommen Fehler im ersten Fall kompilieren:

kann nicht Typ 'Object []' auf 'T' konvertieren

Wenn ich MyWrapper.Value zu T ändern [] Ich:

kann nicht Typ 'Object []' auf 'T []'

Irgendwelche Ideen, wie konvertieren um mein Ziel zu erreichen? Vielen Dank!

+0

Wie wird _wrappedObject definiert? –

+0

_wrappedObject ist mit MyWrapper definiert ist konstruiert. Es benötigt einen ArraySize-Parameter. Für Nicht-Array-Vorlagen gebe ich eine 1 für diesen Wert ein. – bufferz

Antwort

9

bearbeiten Gießen: Aktualisierte Antwort. Die Bibliothek gibt ein Objektarray zurück, Sie können es nicht einfach als T zurückgeben, sei es ein Array oder ein einzelnes Element, ohne etwas damit zu tun. Die folgende Funktion ist ein Beispiel, um ein Array von Objekten aufzunehmen und es entweder als Array oder als einzelnes Element zurückzugeben.

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

Beispiel davon raubend:

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? 
+0

Denken Sie daran, dass T selbst ist ein Array unter diesen Umständen, dh T [] würde ein Array von Arrays darstellen. Also muss ich nur noch T nicht T [] zurückgeben. Ich hoffe das ergibt Sinn. Danke für die Hilfe! – bufferz

+0

Der ursprüngliche Code, der für T zu einem Elementtyp gedacht ist, nicht zu einem Array-Typ. Basierend auf T würden Sie ein Array von T erhalten. Allerdings habe ich den Code mit einer Funktion aktualisiert, die bestimmt, ob T ein Array ist, und entsprechend handeln. –

+0

Das hat genau das gemacht, was ich gesucht habe! Vielen Dank Anthony !!!! – bufferz

2

Sie müssen den Compiler betrügen, indem Sie Ihre Array in ein Objekt zuerst

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

Dies kompiliert, aber denken Sie daran, dass T unter diesen Umständen selbst ein Array ist. Also (T) (Objekt) _wrappedObject.Value wirft und Ausnahme "Kann Objekt vom Typ 'System.Object []' nicht umwandeln, um 'System.Single []'" einzugeben, wenn T ein float [] ist – bufferz