C # 3.0 Auto-Eigenschaften - nützlich oder nicht? [geschlossen]

155

Hinweis: Dies wurde gepostet, als ich mit C # anfing. Mit dem Wissen von 2014 kann ich wirklich sagen, dass Auto-Eigenschaften zu den besten Dingen gehören, die jemals mit der C # -Sprache passiert sind.

Ich bin es gewohnt, meine Eigenschaften in C # mithilfe eines privaten und eines öffentlichen Felds zu erstellen:

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Mit .NET 3.0 haben wir jetzt automatische Eigenschaften:

public string Title { get; set; }

Ich weiß, dass dies eher eine philosophische / subjektive Frage ist, aber gibt es einen Grund, diese Auto-Eigenschaften zu verwenden, außer fünf Codezeilen für jedes Feld zu speichern? Mein persönlicher Kritikpunkt ist, dass diese Eigenschaften Dinge vor mir verbergen, und ich bin kein großer Fan von schwarzer Magie.

Tatsächlich wird das versteckte private Feld nicht einmal im Debugger angezeigt, was in Ordnung ist, da die Funktionen get / set nichts bewirken. Aber wenn ich tatsächlich eine Getter / Setter-Logik implementieren möchte, muss ich trotzdem das private / öffentliche Paar verwenden.

Ich sehe den Vorteil, dass ich viel Code speichere (eine gegen sechs Zeilen), ohne die Fähigkeit zu verlieren, die Getter / Setter-Logik später zu ändern, aber andererseits kann ich das bereits tun, indem ich einfach ein öffentliches Feld "Public string Title" ohne deklariere die Notwendigkeit des {get; einstellen; } blockieren und somit sogar mehr Code speichern.

Also, was vermisse ich hier? Warum sollte jemand eigentlich Auto-Eigenschaften verwenden wollen?

Michael Stum
quelle
86
"Mein persönlicher Kritikpunkt ist, dass diese Eigenschaften Dinge vor mir verbergen, und ich bin kein großer Fan von schwarzer Magie." Huh? Sie sind sich bewusst, dass der Compiler die ganze Zeit eine Tonne vor Ihnen versteckt, oder? Wenn Sie keine Assembly schreiben (oder genauer gesagt die tatsächlichen Einsen und Nullen für Ihren Code), verbirgt ALLES, was Sie schreiben, Dinge vor Ihnen.
Charles Boyung

Antworten:

62

Ja, es wird nur Code gespeichert. Es ist meilenweit einfacher zu lesen, wenn Sie viele davon haben. Sie sind schneller zu schreiben und einfacher zu warten. Das Speichern von Code ist immer ein gutes Ziel.

Sie können verschiedene Bereiche festlegen:

public string PropertyName { get; private set; }

Damit kann die Eigenschaft nur innerhalb der Klasse geändert werden. Dies ist nicht wirklich unveränderlich, da Sie immer noch durch Reflexion auf den privaten Setter zugreifen können.

Ab C # 6 können Sie auch echte readonlyEigenschaften erstellen, dh unveränderliche Eigenschaften, die außerhalb des Konstruktors nicht geändert werden können:

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

Zur Kompilierungszeit wird dies:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

In unveränderlichen Klassen mit vielen Mitgliedern spart dies viel überschüssigen Code.

Keith
quelle
"Sie verlieren also keine Funktionalität." Wie debuggen Sie sie?
Wal
2
@wal - was gibt es zu debuggen? Unter diesem Gesichtspunkt haben Sie es im Wesentlichen mit Mitgliedsvariablen zu tun.
Keith
6
@wal - Sie können einen Haltepunkt auf sie setzen, genau wie Sie auf eine Mitgliedsvariable zugreifen können, können Sie einfach nicht in sie eintreten. Aber warum willst du das? Was die Auto-Eigenschaften tatsächlich tun, ist sowohl trivial als auch automatisch generiert. Wenn Sie Fehler haben, ist dies ein Ort, an dem sie äußerst unwahrscheinlich sind.
Keith
3
Möglicherweise müssen wir dies außerhalb von Keith bringen. :)
Wal
1
Aber ok, nehmen wir an, Sie haben viele Setter-Aufrufe an myObj.Title ... Sie möchten sehen, wo sich der Wert von "text" auf null ändert, dh einen bedingten Haltepunkt. Wie erreichst du das? Sie können nicht einmal einen Haltepunkt auf dem Setter setzen
Wal
45

Die drei großen Nachteile der Verwendung von Feldern anstelle von Eigenschaften sind:

  1. Sie können nicht an ein Feld binden, wohingegen Sie an eine Eigenschaft
  2. Wenn Sie zunächst ein Feld verwenden, können Sie es später (einfach) nicht in eine Eigenschaft ändern
  3. Es gibt einige Attribute, die Sie einer Eigenschaft hinzufügen können, die Sie einem Feld nicht hinzufügen können
Lomaxx
quelle
7
"Wenn Sie anfangen, ein Feld zu verwenden, können Sie es später (einfach) nicht in eine Eigenschaft ändern", sorry, aber warum?
Homam
6
@Homam Hauptsächlich würde jeder Consumer-Code, der die Reflexion Ihrer Felder verwendet, beschädigt, da er von FieldInfo zu PropertyInfo wechseln müsste.
WCWedin
8
@Homam Wenn Sie ein Feld in eine Eigenschaft ändern, wird die Binärkompatibilität unterbrochen, sodass alle Benutzer des Felds neu kompiliert werden müssen.
Odrade
1
Abgesehen von Problemen bei der Neukompilierung und Reflexion ist es sehr einfach, Felder mit Visual Studio zu kapseln: Mit Strg-R + E können Sie ein Feld in eine Eigenschaft mit geeigneten Gettern / Setzern verwandeln. (oder klicken Sie mit der rechten Maustaste auf das Feld, faktorisieren Sie es, kapseln Sie das Feld).
JoeBrockhaus
@ Hommam-Felder sind l-Werte (sie sind Variablen) und Eigenschaften nicht. Dinge, die möglicherweise kompiliert wurden, als es sich um ein Feld handelte, möglicherweise nicht, wenn es sich um eine Eigenschaft handelt.
Mark
29

Ich persönlich liebe Auto-Eigenschaften. Was ist falsch daran, die Codezeilen zu speichern? Wenn Sie Dinge in Getter oder Setter tun möchten, ist es kein Problem, sie später in normale Eigenschaften umzuwandeln.

Wie Sie sagten, könnten Sie Felder verwenden, und wenn Sie ihnen später Logik hinzufügen möchten, würden Sie sie in Eigenschaften konvertieren. Dies kann jedoch zu Problemen bei der Verwendung von Reflexion führen (und möglicherweise auch anderswo?).

Mit den Eigenschaften können Sie auch verschiedene Zugriffsebenen für den Getter und den Setter festlegen, die Sie mit einem Feld nicht ausführen können.

Ich denke, es ist das gleiche wie das Schlüsselwort var. Eine Frage der persönlichen Präferenz.

Strahl
quelle
29

Von Bjarne Stroustrup, dem Erfinder von C ++:

Ich mag keine Klassen mit vielen Get- und Set-Funktionen. Das ist oft ein Hinweis darauf, dass es überhaupt keine Klasse sein sollte. Es ist nur eine Datenstruktur. Und wenn es sich wirklich um eine Datenstruktur handelt, machen Sie sie zu einer Datenstruktur.

Und weisst du was? Er hat recht. Wie oft wickeln Sie einfach private Felder in ein get and set ein, ohne tatsächlich etwas innerhalb des get / set zu tun, einfach weil es die "objektorientierte" Sache ist, die zu tun ist. Dies ist die Lösung von Microsoft für das Problem. Es handelt sich im Grunde genommen um öffentliche Felder, an die Sie binden können.

Giovanni Galbo
quelle
2
Ich denke wirklich, dass dies mehr Punkte haben sollte. Viel zu viele Menschen sehen Autoeigenschaften als grünes Licht für das Schreiben von schrecklich gekapselten (oder überhaupt nicht gekapselten) Klassen, die kaum mehr als ein verherrlichtes öffentliches Feld sind. Natürlich ist dies eher ein Problem bei der Verwendung des Tools als bei dem Tool selbst, aber ich denke, es ist wichtig zu erwähnen, wenn Eigenschaften im Allgemeinen besprochen werden.
Sara
18

Eine Sache, die anscheinend niemand erwähnt hat, ist, dass Autoeigenschaften für unveränderliche Objekte (normalerweise unveränderliche Strukturen) leider nicht nützlich sind. Denn dafür solltest du wirklich tun:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(wobei das Feld im Konstruktor über einen übergebenen Parameter initialisiert und dann schreibgeschützt wird.)

Dies hat also Vorteile gegenüber einer einfachen get/ private setautoproperty.

Domenic
quelle
Wenn eine Struktur eine Eigenschaft ändert, führt dies zu einer neuen Struktur. Dies wäre nur dann ein Problem, wenn Sie einen intern unveränderlichen Referenztyp wünschen - ich kann keinen Grund erkennen, warum Sie jemals einen benötigen würden.
Keith
@ Keith: Dein erster Satz scheint sachlich falsch zu sein.
Domenic
3
Würde nicht public string Title { get; private set; }genau das Gleiche ergeben? Sie könnten es dann natürlich innerhalb der Klasse ändern, aber wenn Sie das tun, haben Sie andere Probleme ...: p
Svish
2
@Svish - durch dieses Argument sollte das schreibgeschützte Schlüsselwort in C # niemals verwendet werden, da seine Verwendung bedeuten würde, dass wir diese "verschiedenen Probleme" versteckten
Zaid Masud
2
Ich meine nur, dass es aus Sicht einer externen API keinen großen Unterschied machen würde. Auf Wunsch können auch Auto-Eigenschaften verwendet werden. Das Beste wäre natürlich, wenn Sie so etwas tun könntenpublic string Title { get; private readonly set; }
Svish
12

Ich erstelle immer Eigenschaften anstelle von öffentlichen Feldern, weil Sie Eigenschaften in einer Schnittstellendefinition verwenden können, Sie können keine öffentlichen Felder in einer Schnittstellendefinition verwenden.

Das Ö
quelle
8

Auto-Eigenschaften sind genauso eine schwarze Magie wie alles andere in C #. Wenn Sie erst einmal darüber nachdenken, wie Sie zu IL kompilieren können, anstatt es zuerst zu einer normalen C # -Eigenschaft zu erweitern, ist es viel weniger schwarze Magie als viele andere Sprachkonstrukte.

ICR
quelle
5

Ich benutze die ganze Zeit Auto-Eigenschaften. Vor C # 3 konnte ich mich nicht mit der ganzen Eingabe beschäftigen und verwendete stattdessen nur öffentliche Variablen.

Das einzige, was ich vermisse, ist, dies tun zu können:

public string Name = "DefaultName";

Sie müssen die Standardeinstellungen in Ihre Konstruktoren mit Eigenschaften verschieben. langweilig :-(

Orion Edwards
quelle
4
Mit Auto-Property-Initialisierern von C # 6 können Sie dies bald tun: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Carlos Muñoz
5

Ich denke, jedes Konstrukt, das intuitiv ist UND die Codezeilen reduziert, ist ein großes Plus.

Diese Art von Funktionen macht Sprachen wie Ruby so leistungsfähig (diese und dynamische Funktionen, die auch dazu beitragen, überschüssigen Code zu reduzieren).

Ruby hatte dies die ganze Zeit als:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter
Mike Stone
quelle
2

Das einzige Problem, das ich mit ihnen habe, ist, dass sie nicht weit genug gehen. Dieselbe Version des Compilers, die automatische Eigenschaften hinzugefügt hat, hat Teilmethoden hinzugefügt. Warum sie die beiden nicht zusammengefügt haben, ist mir ein Rätsel. Ein einfaches "partielles On <PropertyName> Changed" hätte diese Dinge wirklich sehr, sehr nützlich gemacht.

David Wengier
quelle
Sie können mehrere Teilmethoden in eine andere Methode einfügen. Es wäre verwirrend, ein automatisches Muster für sie zu erstellen.
Matthew Whited
2

Es ist einfach, kurz und wenn Sie irgendwo auf der ganzen Linie eine echte Implementierung im Hauptteil der Eigenschaft erstellen möchten, wird die externe Schnittstelle Ihres Typs nicht beschädigt.

So einfach ist das.

Omer van Kloeten
quelle
1

Hierbei ist zu beachten, dass dies meines Wissens nur syntaktischer Zucker am C # 3.0-Ende ist, was bedeutet, dass die vom Compiler generierte IL dieselbe ist. Ich bin damit einverstanden, schwarze Magie zu vermeiden, aber trotzdem sind weniger Zeilen für dieselbe Sache normalerweise eine gute Sache.

pbh101
quelle
1

Meiner Meinung nach sollten Sie immer Auto-Eigenschaften anstelle von öffentlichen Feldern verwenden. Das heißt, hier ist ein Kompromiss:

Beginnen Sie mit einem internen Feld unter Verwendung der Namenskonvention, die Sie für eine Eigenschaft verwenden würden. Wenn Sie zuerst auch

  • benötigen Zugriff auf das Feld von außerhalb seiner Baugruppe, oder
  • müssen Logik an einen Getter / Setter anhängen

Mach das:

  1. Benennen Sie das Feld um
  2. mach es privat
  3. ein öffentliches Eigentum hinzufügen

Ihr Client-Code muss nicht geändert werden.

Eines Tages wird Ihr System jedoch wachsen und Sie werden es in separate Baugruppen und mehrere Lösungen zerlegen. In diesem Fall werden alle exponierten Felder zurückkehren, um Sie zu verfolgen, da das Ändern eines öffentlichen Felds in eine öffentliche Eigenschaft , wie Jeff erwähnte, eine brechende API-Änderung darstellt .

ESV
quelle
0

Ich benutze CodeRush, es ist schneller als Auto-Eigenschaften.

Um dies zu tun:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Benötigt insgesamt acht Tastenanschläge.

Brian Leahy
quelle
5
Wenn ich STRG und V gedrückt halte, kann ich viele, viele Dinge einfügen, / sehr schnell /, aber das macht es nicht "besser". Wie beantwortet dies die ursprüngliche Frage?
JBRWilkinson
0

Nun, mit Code-Schnipsel wäre eine gleichnamige Auto-Eigenschaft insgesamt sieben Tastenanschläge;)

ICR
quelle
0

@Domenic: Ich verstehe es nicht. Kannst du das nicht mit Auto-Eigenschaften machen?:

public string Title { get; }

oder

public string Title { get; private set; }

Beziehen Sie sich darauf?

Andrei Rînea
quelle
Sie können (Letzteres; Ersteres wird nicht kompiliert), aber dann ist das Feld in Ihrem Objekt nicht unveränderlich.
Domenic
Achtung, nur Strukturen sind unveränderlich, wenn sie schreibgeschützt markiert sind. Klassen sind einfach nicht zuweisbar.
Guvante
0

Mein größter Kritikpunkt an Auto-Eigenschaften ist, dass sie Zeit sparen sollen, aber ich finde oft, dass ich sie später zu vollständigen Eigenschaften erweitern muss.

Was VS2008 fehlt, ist ein Refode Auto-Property Refactor.

Die Tatsache, dass wir einen gekapselten Feldrefaktor haben, macht es mir schneller, nur öffentliche Felder zu verwenden.

Johnno Nolan
quelle