Welche ist am besten für Daten speichern Struct-Klassen?
Wir haben gesehen, viel diskutiert in SO in Bezug auf die class vs. struct in c#. Meistens endete mit Schlussfolgerungen zu sagen, die eine heap/stack memory allocation. Und die Empfehlung zu verwenden Strukturen in kleinen Datenstrukturen.
Nun habe ich einer situation zu entscheiden, das einfache speichern von Daten unter diesen beiden Möglichkeiten. Derzeit in unserer Anwendung haben wir Tausende von Klassen, fungiert einfach als einfachen datenspeicher (nur in exponierten öffentlichen Bereichen) und Sie bestanden unter verschiedenen Modulen und services.
Gemäß meinem Verständnis, ich fühlte, dass es besser voran, mit struct statt Klassen für die performance-Gründen. Denn diese sind einfache Daten-Strukturen nur als datenspeicher.
Bevor Sie mit diesem, ich brauche eine kompetente Beratung von Menschen, die das erlebt haben, diesen Kampf zu führen.
- ist mein Verständnis richtig?
- Ich habe gesehen die meisten ORMs haben Klassen als Daten speichert. So bezweifle ich, es sollte einen Grund Voraus gehen, die mit Klassen anstatt structs. was könnte das sein?
- ORM-Objekte sind nicht "normal-alten" struct-Daten, denn Sie wickeln sich um andere Daten zu speichern, die Abstraktion der Datenbank-Komponente Weg, so wie es aussieht bist du nur Zugriff auf ein Objekt. All das geschieht mit Methoden und Reflexion, die Funktionen einer Klasse.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde die Wahl treffen, basierend auf den folgenden Kriterien
Ist ziemlich cool, nicht so bekannt Vorteil von Structs Klassen ist, dass es eine automatische Implementierung von GetHashcode und Equals in Strukturen.
Das ist ziemlich nützlich, wenn Tasten sind erforderlich für Wörterbücher
Struct Implementierung von GetHashcode und Equals basierend auf dem binären Inhalt des struct-Instanzen + Reflexion für die Referenz-Mitgliedern (wie String-Mitgliedern und anderen Instanzen von Klassen)
Also der folgende code funktioniert für GethashCode/Entspricht :
Beide Behauptungen sind dann erfolgreich, wenn die Person ist eine Struktur, die
Beide assertions fehlschlagen, wenn die Person eine Klasse statt einer Struktur
Referenz :
https://msdn.microsoft.com/en-Us/library/2dts52z7%28v=vs.110%29.aspx
Grüße, besten Kodierung
Strukturen definiert werden sollte, unveränderlich, wo in Klassen sollten nicht. Wenn Sie denken, dass Ihre Objekte werden kleine und unveränderliche können Sie voran gehen mit Ihnen Strukturen, oder sonst lassen Sie es Klassen.
Rectangle
waren eine veränderliche Klasse anstelle eines struct. Es wäre völlig unklar, was passieren soll, wenn man versuchtMyControl.Bounds.Width += 20;
. Die Tatsache, dassBounds
ist eine Struktur, anstatt eine Klasse macht deutlich, dass die oben nicht funktioniert (es wird nicht selbst kompiliert), und das muß man entweder kopierenBounds
um eine temporäreRectangle
ändern, und dann Grenzen setzen mit dem neuen Rechteck, oder sonst einige andere Mittel...Bounds
, man hätte doch die Suche über die definition vonControl
; durch Kontrast, kopierenBounds
um eine temporäreRectangle
ist, ändern Sie es, und setzen es wieder funktioniert, genau so sollte man erwarten, dass nur die Informationen, dieRectangle
ist eine Struktur mit änderbaren Felder, undBounds
ist ein nur-lese-Eigenschaft von TypRectangle
. Keine weitere Dokumentation erforderlich.Kann ich nie wirklich daran erinnern, genau wie die Strukturen sind unterschiedlich, aber Sie sind. Auf subtile Weise. In der Tat, manchmal Sie kommen und beißen Sie.
So. Es sei denn, Sie wissen, was Sie tun, halte dich einfach an den Klassen.
Ich weiß, das klingt ein wenig newbie. Ich weiß, ich sollte jetzt gehen und suchen Sie die Unterschiede und zeigen Sie hier - aber das wurde auch schon von anderen getan. Alles was ich sage ist, dass das hinzufügen einer anderen Art von Objekten erstellt eine semantische Last, die ein wenig zusätzliche Komplexität, die Sie klug sind, sorgfältig zu prüfen.
Wenn ich mich richtig erinnere, eines der größten problem ist der Wert, der Semantik der Strukturen: Übergeben Sie Sie um, erhalten Sie unterschiedliche Objekte (wie Sie erhalten, übergeben durch Wert). Wenn Sie dann ändern einiger Felder in einem Ort, beachten Sie, dass in allen anderen Orten wird das Feld nicht geändert werden! Das ist, warum jeder ist zu empfehlen Unveränderlichkeit für structs!
EDIT: Für den Fall, das Sie beschreiben, structs funktionieren nicht!
P
undQ
TypPoint
(das ist ein struct mit den FeldernX
undY
), sagteP=Q;
entsprichtP.X=Q.X; P.Y=Q.Y;
. Beachten Sie, dass das kopieren eines struct wird kopieren Sie alle Felder, öffentliche und private. Wenn Sie denken, der Dinge in dieser Hinsicht wird es offensichtlich sein, warum die Strukturen Verhalten sich anders als Klassen. In Bezug auf Strukturen und Klassen als "fast das gleiche" ist unklug. Die Tatsache, dass .net implizit definiert für jede struct eine Klasse, die den gleichen Namen hat, Felder, Eigenschaften und Methoden stellen Strukturen scheinen wie Klassen...Point
zuObject
es umgewandelt werden in ein Klassenobjekt vom TypPoint
. Wenn Sie die Umwandlung das Objekt zurückPoint
und speichern Sie in einer Variablen von diesem Typ, FelderX
undY
, die das Objekt kopiert werdenPoint
variable.Einem class-Objekt hat den Vorteil, dass es möglich ist, zu passieren um einen Verweis darauf, mit der der Geltungsbereich und die Lebensdauer von solchen Verweis als unbegrenzt, wenn es erreicht außerhalb-code. Ein struct hat den Vorteil, dass, während es möglich ist, zu passieren um kurzlebige Verweise auf Sie, es ist nicht möglich passieren um unbefristete promiscuous-Referenzen. Dies hilft zu vermeiden, dass sorgen darüber, ob solche Verweise vorhanden sind.
Einige Leute haben vorgeschlagen, dass die Daten zu Haltern, die wandelbar ist, sollte nicht Strukturen. Ich distanziere mich ausdrücklich. Unternehmen, die vorhanden ist, für den Zweck der holding-Daten sollten in vielen Fällen werden Strukturen, vor allem, wenn Sie sind veränderlich. Eric Lippert hat geschrieben vielen Male, die er als veränderliche value-Typen böse (Suche nach tags, die "mutable" und "struct"). Es ist sicherlich wahr, dass .net ermöglicht es, bestimmte Dinge zu tun, die mit mutable structs, die es nicht sollte, und nicht bequem erlauben, einige Dinge, die es sollte, aber POD ("Plain Old Data") Strukturen, die keine mutierend Methoden, sondern setzen Ihre ganze Staat über die öffentlichen Felder, haben eine sehr nützliche Konsistenz in Ihrem Verhalten, die nicht gemeinsam mit einem anderen Datentyp. Mit einem POD-struct verwechseln kann jemand, der nicht vertraut mit, wie Sie arbeiten, sondern machen das Programm viel besser lesbar, indem Sie jeden, der tut.
Betrachten Sie beispielsweise den folgenden code, vorausgesetzt, EmployeeInfoStruct enthält nichts als Wert-Typen und unveränderlich Klassentypen wie String:
Eric Lippert beschwert sich, dass der obige code ändert den Wert in anEmployee, aber, dass die änderung keine Auswirkungen auf den container. Ich würde vorschlagen, dass ist eine gute Sache-wer weiß, wie Strukturen funktionieren könnte, sehen Sie in der obigen code und wissen, schreibt in eine struct-variable beeinflussen, dass Variablen, aber nicht auf irgendetwas anderes, es sei denn später das Programm verwendet eine andere Methode (vielleicht SetEmployeeInfo) zu speichern, die variable irgendwo.
Nun ersetzen EmployeeInfoStruct mit EmployeeInfoClass, die eine lese - /schreibeigenschaft vom Typ YearlyBonus. Nur mit den oben genannten Informationen, was kann man sagen über die Beziehung zwischen schreibt someEmployeeContainer und anEmployee? Abhängig von den Implementierungen der anEmployee s-Klasse (die, es sei denn, EmployeeInfoClass versiegelt ist, könnte oder könnte nicht, tatsächlich EmployeeInfoClass) und someEmployeeContainer, die Beziehung zwischen den Objekten kann alles mögliche sein. Schreibt man vielleicht:
Mit Strukturen, die nichts enthält aber Felder, die entweder Wert-Typen oder unveränderlich - Klassen, die die Semantik wird immer #1. Man muss nicht Blick auf den code für das struct selbst, noch der code des Containers, um das zu wissen. Im Gegensatz dazu, wenn die anEmployee.Gehalt oder someEmployeeContainer.GetEmployee virtuell ist, ist es unmöglich, wirklich zu wissen, was der Semantik werden.
Es ist wichtig zu beachten, dass, wenn Strukturen sind groß, übergabe nach Wert oder der Rückgabe von Funktionen kann teuer werden. Es ist generell besser, übergeben Sie große Strukturen als
ref
- Parameter, wenn möglich. Obwohl die integrierte-in-Sammlungen wirklich nicht tun, einen guten job zu erleichtern, eine solche Nutzung, kann es mit einer Hunderte-von-Byte struct billiger als die Verwendung einer Klasse.Den Kommentar über Strukturen Unveränderbarkeit korrekt ist. Und das ist, wo es kann dich beißen. Sie können definieren, Strukturen mit Feld-setter, aber wenn Sie einen Feldwert ändern, wird eine neue Instanz erstellt. Also, wenn Sie halten eine Referenz auf das alte Objekt, es wird immer noch Bezug auf den alten Wert. Ich weiß nicht, wie mit veränderlichen stucts aus diesem Grund als diese produzieren können subtile und komplexe bugs (vor allem wenn Sie mit komplexen, zusammengesetzten Aussagen).
Auf der anderen Seite gibt es viele gute Gründe für die Verwendung von Klassen mit unveränderlichen Zustand auch (denke Zeichenfolge).
Ich erinnere mich an eine Beratung auf der MSDN-Website, die Struktur sollte nicht larget als 16 oder 21 Byte. Auf der Suche für den link, aber kann ihn nicht finden noch.
Die wichtigste Implikation war, dass, sobald Sie einen string in Ihre Daten geben - damit es eine Klasse, ohne zu denken. Ansonsten ist die Struktur sollte nicht all zu viel.
Ich glaube, Sie haben die richtige Idee. Strukturen werden gemacht nachzuahmen Daten-Typen. Sie sind Wert-getrieben, nicht-Referenz basiert. Wenn man sich die MSDN-Dokumentation für die meisten der base-Klassen-Daten (int, double, decimal, ect.) Sie basieren alle auf structs. Das sagte jedoch, die Strukturen sollten nicht zu Häufig benutzt werden, für die sehr gleichen Grund. Platz für alle alles, was in dieser Struktur zugeordnet wird, sobald es instanziiert ist, wo, wie Klassen nur reservieren Zimmer für einen Verweis auf den gesamten Inhalt. Wenn die Daten in klein genug Stücke, wo dies kein problem ist, als Strukturen sind der Weg zu gehen. Wenn dies ein Problem ist, gehen Sie mit Klassen. Wenn Sie nicht wissen, als es könnte nur sein, am besten, stick mit was Sie vertraut sind mit.
Wenn Sie low-latency-Anforderungen und EINE Vielzahl von Objekten langsame garbage Collection kann ein problem sein. In diesem Fall struct kann sehr hilfreich sein, da der garbage collector nicht prüfen müssen, durch eine Hierarchie von Werttypen, wenn die Wert-Typen enthält keine Referenztypen.
Finden Sie eine benchmark hier: http://00sharp.wordpress.com/2013/07/03/a-case-for-the-struct/