2010-10-03 5 views
5

Ich habe dies:Warum mit Initializern zu tun haben? (.net)

AudioPlayer player = new AudioPlayer(); 
player.Directory = vc.Directory; 
player.StartTime = vc.StarTime; 
player.EndTime = vc.EndTime; 

Aber ich könnte dies:

AudioPlayer player = new AudioPlayer 
{ 
    Directory = vc.Directory, 
    StartTime = vc.StarTime, 
    EndTime = vc.EndTime 
}; 

Wenn ich auf ‚neue Art des Schreibens Dinge‘ umwandeln, was erhalte ich neben Unlesbarkeit? Wird es mich näher an Lambda-Funktionen bringen (=>)?

Hat es etwas mit RAII zu tun?

ADDITION:

Einige antworteten, dass normale Initialisierung nach dem Objekt in ‚ungültig‘ Zustand belassen könnte zum Beispiel nur ein Verzeichnis-Eigenschaft - meine Beobachtung hier ist, dass jemand, der das Objekt der Gestaltung wurde wahrscheinlich in ein konstruiertes Auf diese Weise werden nur Werte, die wirklich eingegeben werden müssen, durch den echten Konstruktor eingegeben, und alle anderen können später frei modifiziert werden.

+0

Nun, es scheint, als ob meine Ahnung von Lambda richtig war! –

+0

Überprüfen Sie Ihr bevorzugtes C# -Sprachbuch auf "anonyme Typen". –

+0

@Hans: wie in 'Ad-hoc-Property-Container'? –

Antwort

2

Sie möchten Ihr neu erstelltes Objekt an eine Methode übergeben (und nichts anderes damit tun). Sie können entweder auf die alte Weise schreiben:

AudioPlayer player = new AudioPlayer(); 
player.Directory = vc.Directory; 
player.StartTime = vc.StarTime; 
player.EndTime = vc.EndTime; 
some.Method(player); 

Oder können Sie Objektinitialisierer verwenden:

some.Method(
    new AudioPlayer 
    { 
     Directory = vc.Directory, 
     StartTime = vc.StarTime, 
     EndTime = vc.EndTime 
    }); 

Objekt initilizers verwenden, können Sie deutlich sehen, was der Code tut und dass das Objekt nicht verwendet wird später .

Auch denke ich, die Lesbarkeit (und "Schreibbarkeit") ist besser: Sie müssen den Variablennamen nicht endlos wiederholen.

+0

Nun, hier kommt das 'mit' Schlüsselwort von VB6! :) –

1

Ich glaube, diese Syntax wurde hinzugefügt, weil es einfacher ist, mit Lambda-Ausdruck zu verwenden, so dass Sie leicht wie item => new Person() { Name = item.Name } tun können.

Ich glaube nicht, dass irgendetwas hat allerdings mit RAII zu tun ..

10

Mit solch einem einfachen Beispiel, Sie tatsächlich gewinnt nicht viel. Es wird jedoch anders, wenn Sie dies haben:

var player = new AudioPlayer 
{ 
    Car = new Car() 
    { 
     WheelSize = new Inch(21), 
     Driver = new Person() 
     { 
      Age = 53, 
      Type = LicenseType.B, 
      Family = 
      { 
       new Person("Jane"), 
       new Person("Pieter"), 
       new Person("Anny") 
      } 
     } 
    } 
    Directory = vc.Directory, 
    StartTime = vc.StarTime, 
    EndTime = vc.EndTime 
}; 

Versuchen Sie, dies mit der alten Art und Weise zu tun. Es wird wirklich hässlich.

+0

+1. Ein trivialer Punkt, aber die Parameter sind beim Aufruf des parameterlosen Konstruktors nicht erforderlich. – Ani

+0

@Ani: Deshalb hat 'neuer AudioPlayer' keine Klammern :-) – Steven

1

Sie erhalten 21 Zeichen weniger Code. Und weniger Code bedeutet weniger Fehler. Und um noch mehr zu gewinnen, könnte man implizite Variablentyp-Inferenz verwenden: var player = new AudioPlayer {

2

Sie erhalten nicht nur Unlesbarkeit, Sie erhalten auch eine größere Fähigkeit, Fehler zu verursachen, indem Sie Objekte in einen ungültigen Zustand versetzen.

Das einzige, was es mit RAII zu tun hat, ist, dass RAII von vernünftigen Invarianten abhängt, und Initialisierer machen es einfach, Invarianten zu brechen.

Es kann jedoch sehr nützlich beim Erstellen eines anonymen Werts oder beim Erstellen von Plain-Old-Data-Stilobjekten sein (wobei die Klasse ein "dummer" Container mit Werten und Invarianten ist, nicht so wichtig). Diese können besonders nützlich bei Lambda-Funktionen und Linq-Ausdrücken sein, sind jedoch weder für sie absolut notwendig noch auf diese beschränkt.

Wenn eine Klasse eine Invariante verwaltet, ist es keine gute Idee, sie so zu initialisieren, und in der Regel ist ein Umschreiben von einem Konstruktor, das Werte für die neue Syntax annimmt, eine schlechte Idee.

In Ihrem Beispiel verwendet der erste Fall seinen Konstruktor nicht, um einen garantierten gültigen Zustand zu initialisieren. Das ist ein schlechter Geruch (was soll ein Spieler tun, bevor er ein Verzeichnis hat, Startzeit und Endzeit?), Aber wenn es für eine bestimmte Klasse sinnvoll ist, dann wird auch die neue Syntax verwendet.

Dass die neue Syntax das Objekt in einem einzelnen Ausdruck einrichten kann, der wiederum Teil eines anderen Ausdrucks sein kann, ist, wo dies nützlich sein könnte, und ja, das in Lambda-Ausdrücke enthalten ist.

2

Initiatoren werden benötigt, und nicht nur nützlich, wenn es um anonyme Typen geht.

z.B .:

var x = new {Foo = "foo", Bar = "bar"};

+0

Diese bestimmte Instanz, ist es kompatibel mit .net 2.0? I.e. Ist es ein Feature einer IDE, eines Compilers oder einer .NET-Laufzeitumgebung? –

Verwandte Themen