2016-06-08 11 views
2
immutable auto a = Array!int([1, 2, 3]); 

Error: cannot implicitly convert expression (((Array!int __slArray2557 = Array(RefCounted(RefCountedStore(null)));) , __slArray2557).this([1, 2, 3])) of type Array!int to immutable(Array!int)Erstellen von benutzerdefinierten unveränderliche Objekte

Oft möchte ich nur einige Objekt zur Laufzeit erstellen, sie initialisieren und dann unveränderlich machen, aber wenn ich versuche, dies zu tun, erhalte ich den Fehler von oben.

Es scheint, dass ich ein veränderbares Objekt auf ein unveränderliches Objekt werfen kann

immutable auto a = cast(immutable Array!int) Array!int([1, 2, 3]); 

Warum muss ich es immutable werfen?

Ist Casting zu unveränderlich sogar legal?

+0

Ich weiß eigentlich fast nichts über D, aber wenn Sie eine Variable als unveränderlich deklarieren, wird der Compiler wahrscheinlich erwarten, dass der Ausdruck auf der rechten Seite ein unveränderliches Objekt ist, also natürlich, wenn das nicht der Fall ist, wird es Ihnen wahrscheinlich geben ein Fehler. Ob es legal ist oder nicht, weiß ich nicht, aber wenn Sie keine Antwort erhalten, empfehle ich Ihnen, diese Frage in einem der D-Foren auf der offiziellen Website zu stellen. – nbro

Antwort

6

Da Array Referenz gezählt wird, ist es nicht kompatibel mit unveränderlich jetzt - es hält einen Zeiger auf eine Referenz zählen in ihm, die nicht ändern kann, wenn es unveränderlich ist, das ganze Ding zu brechen. Der Cast umgeht nur die Regeln, die kompiliert, aber nicht definiert ist.

Wenn es unveränderlich ist, Graben nur die Array Wrapper und verwendet eine gewöhnliche Scheibe:

// this works fine 
immutable a = [1, 2, 3]; 

(Heck, der Array-Wrapper ist im Grunde nutzlos, wenn man es wörtlich sowieso passieren, da die gewöhnliche Anordnung aufgebaut ist, nur an den Konstruktor übergeben, wo es wieder aufgebaut wird!)

BTW die auto in immutable auto nicht erforderlich ist, können Sie es nur immutable nennen.

Sie könnten auch ein veränderbares Array von unveränderlichen Daten erstellen, das sollte auch funktionieren - es braucht nur wegen seiner Speicherverwaltung Schema.

+0

Gibt es eine Dokumentation darüber, was unveränderlich sein kann? Es scheint, dass wenn ich einen benutzerdefinierten Typ erstellen, der einen Zeiger oder ein Segment enthält, nicht unveränderlich sein kann. Ich denke, was ich wirklich wollte, war wahrscheinlich nur const. –

+0

const würde auch nicht mit Referenzzählung arbeiten. Aber im Allgemeinen, wenn Sie wissen möchten, ob ein Typ mit const oder unveränderlich arbeitet, beginnen Sie, indem Sie auf seine Mitgliedsfunktionen schauen und sehen, welche const, immutable oder inout sind. Funktionen, die keine von ihnen haben, funktionieren definitiv nicht mit 'const' oder' unveränderlich'. Wenn genug von ihnen mit diesen Attributen markiert sind, wird es wahrscheinlich funktionieren, obwohl, wenn die Dokumentation nicht sagt, und Sie nicht mit einem ziemlich einfachen Typ beschäftigen, gibt es eine gute Chance, dass 'unveränderlich' nicht funktioniert. Ein weiterer guter Hinweis ist, wenn es als unveränderlich konstruiert werden kann. –

+0

Ich denke, das ist der neueste Artikel über unveränderlich: http://dlang.org/spec/const3.html aber im Grunde die Regel ist nur, dass, sobald Sie Const/unveränderlichen Land eingeben, verlassen Sie es nie. Wenn also die äußere Schicht unveränderlich ist, sind es auch alle Mitglieder und alle Daten, auf die die Mitglieder zeigen, und so weiter. Eine unveränderbare Variable kann nicht durch irgendetwas geändert werden - einschließlich der internen Größenänderung und Freigabe von Zeigern, die auch Strukturzuweisungen enthalten. Nur wenn es keine weiteren Referenzen mehr gibt, kann das Programm frei werden, so dass das Programm nie weiß, dass es nur eine Illusion war (daher kann der GC es freigeben, aber Sie können es nicht.) –