Ich erstelle eine Geometriebibliothek in C # und ich benötige die folgenden unveränderlichen Typen:
Vector2f
(2 float
s - 8 Bytes) Vector2d
(2 double
s - 16 Bytes) Vector3f
(3 float
s - 12 Bytes) Vector3d
(3 double
s - 24 Bytes) Vector4f
(4 float
s - 16 Bytes) Vector4d
(4 double
s - 32 Bytes) Ich versuche herauszufinden, ob ich sie zu Strukturen oder Klassen machen soll. MSDN schlägt vor, nur eine Struktur zu verwenden, wenn die Größe nicht größer als 16 Byte sein soll. Diese Referenz scheint von 2005 zu sein. Sind 16 Bytes immer noch die maximal vorgeschlagene Größe?
Ich bin sicher, dass die Verwendung von Strukturen für die float
Vektoren effizienter wäre als die Verwendung einer Klasse, aber was soll ich mit den double
Vektoren machen? Soll ich ihnen Strukturen machen, damit sie konsistent sind, oder sollte ich ihnen Klassen geben?
Aktualisiert: Sieht so aus, als würden alle zustimmen, dass sie Strukturen sein sollten. Danke für die tollen Antworten.
Ich würde im Allgemeinen Typen wie diese Strukturen machen. Strukturen werden mit größerer Wahrscheinlichkeit auf dem Stapel platziert, und wenn Sie Arrays mit ihnen verwenden, können Sie viel bessere Leistung erzielen, als wenn Sie z. B. eine Liste & lt; & gt; von Objekten. Solange Sie sich von Operationen fernhalten, die dazu führen, dass Ihre Vektorklassen eingerahmt werden, ist die Struktur im Allgemeinen der leistungsfähigere Weg.
Unveränderbare Strukturen sind eine gute Wahl. Die Größenempfehlung auf MSDN ist die schwächste, 32 Byte sind nicht wirklich groß.
Das Hauptargument wäre, dass Vektoren wie einfache (numerische) Typen verwendet werden und eine Implementierung als Werttyp am besten geeignet ist.
Eine gute Parallele sind die neuen Komplexe und BigInteger Strukturen in dotNet 4
Structs, definitiv. Warum? Nun, es ist Teil Gefühl, ich denke, ein Vektor fühlt sich einfach und benimmt sich wie ein Wert .
Rico Mariani hier gibt einige Gründe an, warum Werttypen für bestimmte ausgewählt wurden Typen für eine API (ich glaube nicht, dass es XNA ist, über die er spricht).
Und obwohl Effizienz hier eine Rolle spielt, denke ich nicht, dass es um Garbage Collection geht, sondern eher um Datendichte wie Rico sagt. Angenommen, Sie haben auch einen Vertex
-Typ, der zwei Vector3
s enthält: a Vector3
für den normalen und% Vector3
für die Weltkoordinaten. Wenn Sie diese Typenklassen erstellt haben, würde ein Array mit 100 Vertex
-Elementen bestehen aus:
Vertex
-Elemente) Vertex
zu den zwei Vector3
Elementen) Vector3
eine Klasse zu machen) float
pro Vector3
) 6000 Bytes (auf einem 32-Bit-System).
Als Werttyp ist es einfach 200 * 12 Bytes = 2400 Bytes. So viel effizienter im Raum, ganz zu schweigen von einem niedrigeren Grad an Indirektion beim Lesen des Arrays.
Wenn Sie jedoch viel Platz einnehmen, wird es nicht unbedingt langsam. Wenn Sie einen Werttyp falsch verwenden, kann das langsamer sein, als wenn Sie ihn zu einer Klasse machen, wie Ich habe es herausgefunden . Sie möchten sie auf jeden Fall so weit wie möglich an ref
übergeben, vermeiden Sie es zu kopieren, aber dies gilt nicht für alle Operationen, also messen Sie. Ich denke, ich erinnere mich, dass das Skalarprodukt bei der Weitergabe von ref
langsamer berechnet wurde, vielleicht weil es irgendwie eine Neuausrichtung verhinderte, indem es die IL größer machte. Aber nehmen Sie mein Wort dafür nicht, messen Sie einfach.
Meiner Meinung nach würde ich mit Strukturen dafür gehen, da sie am häufigsten auf dem Stapel zugewiesen würden, dies würde den Druck auf den GC reduzieren, so dass Ihre Anwendung reibungsloser laufen sollte.
Ein Tipp, Ihre Methoden, die auf den Strukturen existieren, sollten die Argumente wahrscheinlich als Ref- und Out-Argumente nehmen, dies wird den Umfang des Kopierens der Daten reduzieren, der stattfindet, wenn Strukturen übergeben und zurückgegeben werden.
Wir haben kürzlich einige Mathe-Typen (vec3, vec4, Matrizen usw.) umgestellt, um Structs anstelle von Klassen zu verwenden. Außerdem wurde der GC-Druck etwas reduziert (wir hatten Hunderte von Megabyte Vec3) Zuweisungen über einen relativ kurzen Zeitraum, entdeckt über den CLR-Profiler).
Es ist interessant zu bemerken, dass die XNA-Implementierung von Vektoren & amp; Matrizen werden mit Strukturen erstellt. Sie können immer durch Verweis dorthin gehen, wo es angebracht ist, wenn Sie auch an der Leistung interessiert sind.
Ich nehme an, Sie machen sich Sorgen wegen perf?
Wenn sie unveränderlich sind, sollten sie verhaltensmäßig identisch sein. Gehen Sie einfach mit einem, und wenn es sich herausstellt, dass es ein Perf-Problem gibt, wechseln Sie es später.
Wenn Sie überhaupt auf .NET CE abzielen, sollten Sie die Verwendung von Strukturen in Betracht ziehen, da der GC nicht so effizient ist wie die vollständige .NET-Implementierung.
Structs werden (normalerweise) auf dem Stack gespeichert, was sie möglicherweise effizienter macht, aber wahrscheinlich nicht genug, um einen spürbaren Unterschied zu machen.
Tags und Links class c# size performance struct