2009-05-21 7 views
0

Ich möchte IEnumerable-Implementierungen im Speicher mit dieser generischen Erweiterungsmethode, an der ich gerade arbeite, festhalten. Es scheint mit Arrays gut zu funktionieren, scheitert aber mit anderen Sequenzen (Listen und Sammlungen). Hier ist die Methodenimplementierung.Fixieren von IEnumerables in C#

Warum funktioniert es bei einigen Typen nicht, aber bei anderen? Können Sie das Konzept dahinter erklären? Gibt es dafür einen besseren Weg als meinen generischen Ansatz? Vielen Dank.

Antwort

7

Die documentation für GCHandle.Alloc zeigt:

Eine Instanz mit nichtprimitiver (non-blitfähig) Mitglieder nicht verstiftet werden.

Objektverweise sind keine primitiven (aka blitable) Mitglieder. Die Implementierung von Typen wie List<T> usw. verwendet intern Objektreferenzen (z. B. Array-Referenzen). Daher haben sie nicht-primitive Mitglieder und können nicht gepinnt werden.

Arrays sind unterschiedlich: Wenn der Elementtyp des Arrays blittierbar ist (d. H. Ein Werttyp ohne nicht blitbare Felder), kann das Array angeheftet werden. Aber das bedeutet nicht, dass ein Verweis auf das Array angeheftet werden kann; Ein Verweis auf das Array ist nicht das Array. Auflistungsklassen wie List<T> enthalten einen Verweis auf ein internes Speicherarray. Sie sind keine Arrays selbst.

+0

Danke für die Informationen Barry, gut erklärt – gogole

1

Wenn Sie wirklich brauchen dies, empfehle ich Sie rufen Sie .ToArray() und stecken Sie das fest.

Aber Vorsicht, weil IEnumerable selbst verwendet faule Auswertung/verzögerte Ausführung, und so die Werte für die Aufzählung möglicherweise derzeit nicht im Speicher überhaupt sein. In der Tat können Sie sogar ein IEnumerable haben, das nie aufhört.

+0

Hallo Joel, kann nicht glauben, nicht daran gedacht. Ich habe den Anwendungsbereich der Methode auf Arrays von T beschränkt, wobei T eine Struktur ist: public static GCHandle Pin (diese T [] @sequenz) wobei T: struct. Danke für die Information. – gogole

Verwandte Themen