Struct und IDisposable
Frage ich mich, warum es nicht kompilieren?
public static void Main(string[] args)
{
using (MyStruct sss = new MyStruct())
{
sss.s = "fsdfd";//Cannot modify members of 'sss' because it is a 'using variable'
//sss.Set(12); //but it's ok
}
}
public struct MyStruct : IDisposable
{
public int n;
public string s;
public void Set(int n)
{
this.n = n;
}
public void Dispose()
{
Console.WriteLine("dispose");
}
}
UPDATE:
Aber es funktioniert perfekt. Warum?
public static void Main(string[] args)
{
using (MyClass sss = new MyClass())
{
sss.Field = "fsdfd";
}
}
public class MyClass:IDisposable {
public string Property1 { get; set; }
public string Field;
public void Method1 (){}
public void Dispose()
{
Console.WriteLine("dispose class");
}
}
Ich will Menschen Erschießen, wenn ich jemals jemanden gesehen, der die Umsetzung
wird, dass zufällige Leute oder die person, die es umzusetzen? Wäre gut zu wissen.
Sie sollte erklären, warum 🙂 Und ich verstehe immer noch nicht, die Erklärung der Grund für diese. Warum mit der Klasse(N) es anders?
Nebenbei, Sie können es nicht tun, selbst wenn Sie mit einem
Siehe Daniel Earwicker Antwort.
IDisposable
auf eine struct
.wird, dass zufällige Leute oder die person, die es umzusetzen? Wäre gut zu wissen.
Sie sollte erklären, warum 🙂 Und ich verstehe immer noch nicht, die Erklärung der Grund für diese. Warum mit der Klasse(N) es anders?
Nebenbei, Sie können es nicht tun, selbst wenn Sie mit einem
foreach (var sss in new List<MyStruct>())
Siehe Daniel Earwicker Antwort.
InformationsquelleAutor Alexandre | 2011-10-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Klasse und struct-Szenarien sind eigentlich die gleichen, aber Sie sehen verschiedene Effekte.
Beim ändern der Klasse Beispiel :
Erhalten Sie die gleichen Fehler auf den ersten Auftrag.
Die Erklärung ist: Sie können nicht ändern (mutieren) die Verwendung von Variablen. Aber für eine Klasse, gilt für die Referenz, nicht der Instanz.
Und die Lektion ist: nicht verwenden Strukturen. Und vor allem nicht verwenden mutable structs.
etwas, das "veränderlich" ist etwas, das kann sich ändern (mutieren). Ein struct, der kann seinen Wert ändern, heißt eine veränderliche Struktur, und ist im Allgemeinen als etwas schlechtes. Mehr Lesen: Warum sind mutable structs böse?
InformationsquelleAutor Henk Holterman
Einer Anzahl von Menschen verbunden haben, um meinen Artikel über mutierend Wert-Typen und warum es eine schlechte Idee ist. Obwohl es ist wichtig zu verstehen, diese Konzepte, wenn Sie verstehen, warum Ihr eine schlechte Idee, entsorgen Sie ein struct, und eine noch schlechtere Idee, mutieren Sie die Struktur wenn Sie das tun, das ist nicht wirklich den richtigen Artikel zu verlinken. Die, die Sie Lesen wollen, erklärt, dass all dies im qualvollen detail:
http://ericlippert.com/2011/03/14/to-box-or-not-to-box/
Kurz: "mit" macht kopieren von den Wert-Typ, und Sie sind daher die Entsorgung eine Kopie. Das bedeutet, dass Sie müssen sehr vorsichtig sein-wenn der Wert ist, sagen wir, ein OS-handle, möglicherweise gibt es viele Kopien, die Wert herumliegen Speicher, und Sie brauchen, um stellen Sie sicher, dass Sie es entsorgen genau einmal, egal wie viele Kopien es gibt.
Siehe auch Wenn mein struct IDisposable implementiert wird es sein, boxed, wenn verwendet, in einer using-Anweisung?
(Ein Wörterbuch wurde gewählt, da eine beliebige Klasse geben-ich weiß, es ist nicht das beste Beispiel, dass). Wenn someStructType hat einen public int Bereich I, und StructArr ist ein array von someStructType, welche Auswirkungen "StructArr[3].I+=4;" auf StructArr[4].Ich ? Wenn someClassType hat einen public int Bereich I, und ClassArr ist ein array von someClassType, welche Auswirkungen "ClassArr[3].I+=4;" auf ClassArr[4].Ich? Klassen haben sicherlich Ihren Platz, aber wenn ein Typ wird verwendet, um Werte darzustellen, und wenn Wandlungsfähigkeit wäre hilfreich, dann einen änderbaren Wert-Typ ist oft besser geeignet als eine veränderliche Klasse Typ.
Ich kommentierte den Beitrag, den Sie verlinkt, aber kurz gesagt: alles, was man argumentieren kann getan werden, mit unveränderlichen Wert-Typen. Warum sollten Sie speziell veränderlich?
Warholic: Mit einer unveränderlichen Entität, muss man umschreiben, dass alle Felder, wenn man will, zu verändern. Wenn das, was man tun will, ist änderung ein Feld eines struct, würde ich vorschlagen, dass Sie beide klarer und schneller als das erstellen einer neuen Struktur, in der fast alle Felder haben Werte, die zufällig mit denen des ersten. Welchen Vorteil wird gewonnen, indem umschreiben alles, um eine änderung vornehmen?
Wie genau wird mutierend einen Wert vom Typ klar, wenn es einfach ist, Beispiele zu geben, wo mutierend einen Wert geben falsche Ergebnisse? Der Grund, warum Menschen streiten für die Unveränderlichkeit, die auf Wert-Typen ist, gerade weil der Leistungsverlust (wenn überhaupt) lohnt es sich, die Fähigkeit zur Vernunft über den code effektiv. Für die absolute beste performance-kritischen Bereichen veränderliche value-Typen können sehr hilfreich sein (sagen Eckpunkte in ein 3D-Modell), aber diese Arten von Situationen sind wenige und weit zwischen.
InformationsquelleAutor Eric Lippert
Die Idee einer
using
- Anweisung, um sicherzustellen, dass eine Ressource, die entsorgt wird, wenn Sie verlassen den block.Wenn Sie das zuweisen von struct-Variablen, Sie sind effektiv ersetzt es durch ein vollständig neues Objekt von diesem Typ. Also in diesem Zusammenhang hätten Sie entledigte sich das Objekt, das angeblich geht, entsorgt werden.
Sind struct copy-on-write in C# bei der Verwendung von Feldern/Eigenschaften?
Nein, aber die Verwendung (und foreach -) - Konstrukte erstellen Sie eine temporäre variable. - Klassen sind gut, denn dies ist nur ein Referenz.
Nein. Denken Sie darüber, wie Streicher sind manchmal implementiert in C++? Strukturen sind nur mutable-Objekte, die ausschließlich im Besitz der variable, die auf Sie verweist. Die variable kann unveränderlich (wie in diesem Fall), und der Autor des struct kann, markieren Sie die einzelnen Felder innerhalb der Struktur als unveränderlich (über die
readonly
Stichwort).Und in der Tat die (eigentliche) Frage war/sollte sein, "warum die variable ist unveränderlich", und nicht "warum ich nicht benutzen kann-Felder". Und es ist interessant, dass Sie nicht verwenden können auch Eigenschaften (wenn man bedenkt, dass eine Eigenschaft nicht wirklich BRAUCHEN, um zu ändern, ein Feld).
InformationsquelleAutor Daniel Earwicker
Folgendes:
Nun tun:
Diese Drucke:
Genau. Es zeigt, wie es zu tun, wenn Sie wirklich wollte ;P
Dann schreiben Sie es! Die Tatsache, dass das casting um eine Schnittstelle Werttyp Ursachen Boxen (außerhalb des Generika-mit-constraint-Fall) ist nicht erkennbar für 75% der C# - Programmierer 🙂
Ich wirklich nicht wollen, zu fördern 🙂 Es ist akzeptabel, obwohl, wenn der Programmierer weiß, was er/Sie tut genau das.
InformationsquelleAutor leppie
Endlich habe ich es verstanden 🙂 ich werde nach meiner Ansicht 🙂 🙂
Nun...
ist meta-entspricht
mit
readonly
die gleiche Bedeutung hat derreadonly
- Schlüsselwort in der Klasse/struct-Deklaration.Wenn
MyType
ist eine Referenz, dann ist es die Referenz (und nicht das referenzierte Objekt), die "geschützt". So können Sie nicht tun:aber Sie können
in der using-block.
Wenn
MyType
ist ein Werttyp, derreadonly
"modifier" erstreckt sich auf die Felder/Eigenschaften. Damit Sie nicht eingeführt, eine neue Art von "const-ness/readonly-ness" inusing
, Sie benutzten einfach die, die Sie hatten.Also die Frage sollte sein: warum kann ich keine Felder ändern/Eigenschaften
readonly
Wert-Typen?Beachten Sie, dass wenn Sie dies tun:
Ergebnis
also die
using
ist dabei eine "private" Kopiesss
, undsss.n = 12
ist der Zugriff auf die "original" -sss
, währendDispose
ist der Zugriff auf die Kopie.Ich habe die Wahrheit zu sagen, die Tatsache, dass Felder und Eigenschaften von nur-lese-Wert-Typen gelesen-nur nicht so "offensichtlich" ist Da kein echtes deutlich Grund (wenn man bedenkt, dass der value-Typ ist immer noch veränderlich, indem Methoden und Eigenschaften sind ähnlich zu Verfahren, die als Felder). Und die Tatsache, dass die beiden "lese-onlyness" sind die gleichen, ist nicht ersichtlich.
readonly hat nichts mit diesem zu tun. Es ist die Semantik von Strukturen vs. Klassen. die erstere ist durch einen Wert, der letztere ist durch einen Verweis. Wenn Sie 'Referenz' der ehemaligen, wird eine Kopie des Wertes, das zweite eine Kopie der Referenz wird gemacht (aber noch auf dem original-Objekt).
Auch die Tatsache, dass die variable name ist der gleiche (aber unterschiedliche Lage, iow eine frische variable shadowing der vorherigen) ist verwirrend.
Das ist pure smoke. Wenn etwas ist "readonly", dann schreiben es sollte alles explodieren. Der JIT-sollte zumindest Ersatz Aufrufe von Methoden der readonly Instanzen von Strukturen mit Methoden, die eine Exception werfen (und das FAB weiß genau, wenn ein struct ist readonly in den safe-code, denn es kann nicht sein, ref/out, wenn es ohne Verpackung, dann ist es eine Kopie, wenn es ein parameter einer Funktion ist, dann ist es eine Kopie). Wie es ist, es ist nur ein "es ist möglich, es zu tun, aber wir lassen Sie nicht". Der Beweis dafür ist, dass die Eigenschaften sind verboten. Es ist ein synctactical Regel und nicht eine "Notwendigkeit" - Regel.
InformationsquelleAutor xanatos
Innerhalb der using-block, der ein Objekt ist schreibgeschützt und können nicht geändert oder neu zugewiesen.
überprüfen Sie diesen link: http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Diese Antwort ist falsch, re: C# wie es steht - das struct kann nicht neu zugewiesen werden, es kann aber mutiert werden (dessen Inhalt kann geändert werden). Aber mutable structs sind eine schreckliche Idee sei, daher wohl diese Antwort ist richtiger als die Sprache selbst. 🙂
Ich Stimme mit @DanielEarwicker hier.
InformationsquelleAutor Emir Akaydın
Ich bin mir nicht 100% sicher, also bitte jemand mich korrigieren, wenn ich falsch bin.
Dem Grund, dass der compiler ermöglicht das ändern von Feldern einer Klasse in diesem Szenario, aber nicht eine Struktur, ist in Bezug auf die Speicherverwaltung. Im Falle einer Klasse (ich.e Referenz-Typ), die nicht das Objekt, sondern die Referenz selbst ist der Wert. Also, wenn Sie ändern Sie ein Feld in dem Objekt, Sie sind nicht manipulieren Sie den Wert, sondern ein Speicher-block woanders, wird durch den Wert. Im Falle einer struct, das Objekt ist der Wert, so dass, wenn Sie Bearbeiten ein Feld in der Struktur, Sie sind in der Tat die Manipulation der Wert, der als nur-lese-zu dieser Zeit.
Den Grund der compiler wird damit die Methode aufrufen (das wiederum ändert ein Feld) ist einfach, dass es nicht mehr analysieren tief genug, um festzustellen, ob die Methode führt eine solche Modifikation oder nicht.
Gibt es einen (geschlossenen) Fall bei MS-Connect in Bezug auf diese, können Schuppen etwas mehr Licht: Cannot assign to field struct mit IDisposable-und wenn es eine mit variable - CS1654 Fehler
using
(undforeach
), beide erzeugen eine temporäre variable, der zugewiesen wird. In dem Fall der Struktur, wird der Wert kopiert.ja, aber beachten Sie, dass die OP ist nicht die Zuordnung zu der Verwendung von Variablen, sondern ein Feld im Objekt (es ist eine veränderliche Struktur). Oder habe ich da was missverstehen Sie?
Die OP ist die Zuweisung an ein Feld in einer Kopie des struct. Während technisch ist der code gültig ist, wird der compiler lehnt Sie ab, da wird es keine Wirkung haben (und kennzeichnet einen logischen Fehler).
Dies erklärt die Regel, aber nicht der Grund für die Regel. Was war das problem, Sie versucht zu beheben durch die Einführung dieser Regel?
Hinzufügen oben im Kommentar, mit ein paar tricks können Sie rund um diese Einschränkungen. Hinweis: boxed value types.
InformationsquelleAutor Fredrik Mörk
Struct ist als schreibgeschützt gekennzeichnet. Sie versuchen, ändern Sie eine öffentliche member-variable, die die compiler-flags als nur-Lesen-und so verbietet.
Jedoch, den Anruf zu
Set()
ist zulässig, da der compiler hat keine Möglichkeit zu wissen, das der Anruf mutieren wird der Status der Struktur ist. Es ist in der Tat ein cleverer Weg, mutiert ein readonly Wert!Werfen Sie einen Blick auf Eric Lippert ' s post von mutiert readonly-Strukturen für mehr info.
readonly
. Felder werden niemals implizitreadonly
.Auch mit
Set()
zu mutieren einemreadonly
Feld wird nicht funktionieren. Compiler-Fehler.Innerhalb von Set() das Feld ist nicht readonly. Im Beispiel ist aber die struct-Instanz ist readonly, da es innerhalb einer
using
block. Dieser compiler folgert aus diesem, dass jegliche öffentliche Feld auf die Struktur wird auch readonly.Sind Sie falsch. Der compiler funktioniert nicht ableiten, solche details. Sie können nicht mutieren, ein
readonly
- Feld (beachten Sie, nicht der Rede Wert-Semantik als pro structs jetzt, was ich vermute, auf die Sie sich beziehen), außer in den Konstruktor.Ein Lagerort eines Struktur-Typ ist nicht mehr und nicht weniger, als dann Felder, die Art miteinander verkettet. Es ist nicht möglich zu schreiben, um die Felder einer struct, die sich in einem nur-lese-Speicher-Position, noch ist es möglich, übergeben eine nur-lese-struct Position als
ref
parameter. Da Instanz-Mitglieder auf Struktur-Typen nehmenthis
alsref
parameter, es ist nicht wirklich möglich, zum aufrufen von Instanz-Mitglieder auf nur-lese-Strukturen. Leider ist C# geht davon aus, dass wennreadOnlyStruct.method()
nicht passieren könnenreadOnlyStruct
zumethod
alsref
parameter, ...InformationsquelleAutor Sean