Nehmen Sie eine Reihe von beliebigem Werttyp als formaler Parameter
-
05-09-2019 - |
Frage
Ich möchte in der Lage sein, eine Funktion wie
zu erklären,void foo(<any value type>[] data){}
in C # 2.0. Wenn ich erkläre es als
void foo(ValueType[] data){}
es kompiliert, aber dann die Elemente in Daten [] behandelt werden, als ob sie von object
abgeleitet sind, z.B. Ich kann nicht sagen, so etwas wie
fixed (void* pData = data){}
würde Ich mag die Lücke zu vermeiden, nehmen * als Parameter - Ich möchte nur in der Lage sein, jeden beliebigen Wert-Typ-Array zu akzeptieren und dann tut unmanaged Dinge es
.ETA: Auch dies hat das gleiche Problem:
public static unsafe void foo<T>(T[] data) where T:struct{
fixed(void *p = data){}
}
, falls Sie sich wundern. Feste schlägt fehl, da es als verwaltetes Art behandelt wird - CS0208, nicht einen Zeiger auf einen verwalteten Typ deklarieren. Siehe „mm“ weiter unten. Ich glaube, er ist richtig ... es wohl einfach nicht durchgeführt werden.
Lösung
Ich glaube nicht, das möglich ist, mit C #. Structs erben nicht (aber lose) von System.ValueType bis nach der Zeit zu kompilieren, so dass Sie nicht Foo-Methode Signatur über Polymorphismus mithalten können. Generika sind auch gemäß der Sprachspezifikation:
"Ein nicht verwalteter-Typ ist jede Art, die kein Referenz-Typ ist, ein Typ-Parameter , oder ein generischer Struktur-Typ und enthält keine Felder, deren Typ nicht ein nicht verwalteter-Typ. "
Also, warum Sie nicht die Adresse von T erfolgen können [], unabhängig von der Struktur Einschränkung.
Sie könnten einen Strukturtyp deklarieren (sagen wir, Bar) als Argument für Foo, den Code kompilieren, und die Methodensignatur auf der Ebene IL ändern:
.method private hidebysig static void Foo(valuetype [mscorlib]System.ValueType[] args) cil managed
Und dann der Anruf auch:
IL_0020: call void ConsoleApplication1.Program::Foo(valuetype [mscorlib]System.ValueType[])
Während ich konnte das resultierende Programm laufen zu lassen, weiß ich nicht, welche Art von Nebenwirkungen dies hat. Auch wenn Sie die geänderte Funktion verweisen könnten, würden Sie nicht in der Lage sein, es von C # zu nennen, weil wieder structs von System.ValueType erbt erst nach der Kompilierung, so dass die Methodensignatur würde nicht überein.
Andere Tipps
public void foo<T>(params T[] args) where T : struct {
}
public void SomeMethod() {
foo(1, 2, 3, 4);
}
Sie sollten nicht den generischen Parameter eingeben müssen, da der Compiler auf dem Typ aus dem ersten Parameter von foo abholt.
Das würde funktionieren:
public static void foo(System.Array data)
{
}
static void Main(string[] args)
{
foo(new int[10]);
}
Es erzwingt nicht, dass das Array ist ein Array von Werttypen, aber es funktionieren würde.