| 

.NET C# Java Javascript Exception

7
Ich war gerade am lesen eines Tutorials und da ist mir eine Frage aufgetaucht. Angenommen, wir erstellen eine einfache Klasse in C# mit einer Variablen.

class Klasse1
{
public string Name;
}


Wo liegt der Unterschied zu so einer Klasse:

class Klasse2
{
private string _name;

public string Name
{
get { return _name; }
set { _name = value; }
}
}


Ich meine, wenn man nur die Variable / Eigenschaft setzen bzw. nur lesen kann, dann ist das für mich ersichtlich. Aber wo liegt genau der Unterschied zwischen Klasse1 und Klasse2 bezüglich der Variable/Eigenschaft Name?
13.04.2012
starki 603 1 8
6 Antworten
16
Technisch gesehen (auf MSIL-Ebene) ist ein Feldzugriff etwas anderes als ein Property-Zugriff. D.h. wenn Du erst mal mit dem Feld arbeitest und später merkst, daß Du doch eine Property brauchst, dann mußt Du jeglichen Code neu übersetzen, der auf das Feld Name zugreift - auch wenn die Syntax für den Zugriff beim Verwender exakt die gleiche ist(*).

Und warum könnte es passieren, dass Du eine Property brauchst?

  • Name soll in ein Interface ausgelagert werden. In Interfaces gibt es keine Felder.
  • Du mußt INotifyPropertyChanged implementieren, so daß für jeden Schreibzugriff auf Name das PropertyChanged-Event ausgelöst wird
  • Du mußt irgendwelche anderen Dinge tun, wann immer auf Name zugegriffen wird
  • Der Wert wird nicht mehr direkt gespeichert, sondern aus anderen Feldern berechnet. Z.B. könnte Name aufgesplittet werden in Vorname und Nachname
  • Es soll nicht mehr jeder in das Feld schreiben können.
  • Du willst Name für Datenbindung verwenden.
  • ...

Weil es also normalerweise nicht abzusehen ist, ob es nicht doch mal eine Property werden soll, und weil das dann eine Änderung mit potentiell größeren Auswirkungen wäre, lohnt es sich, von Anfang an auf Propertys zu setzen.

Außerdem gibt es meist ja auch noch Felder, die privat bleiben sollen, und mit Propertys erreicht man eine bessere Abgrenzung zwischen dem internen Zustand und dem öffentlichen Zugriff auf das Objekt.

Übrigens: mit automatisch implementierten Propertys (für die es obendrein das Code-Snippet "prop" gibt), ist sogar der Schreibaufwand kaum größer:

class Klasse3
{
public string Name { get; set; }
}


(*)Update:
Einen Fall gibt es, in dem der Code des Verwenders nicht nur neu übersetzt, sondern sogar umgeschrieben werden muss, wenn ein Feld durch eine gleichnamige Property ersetzt wird: Felder lassen sich als ref-Parameter an Methoden übergeben, Propertys hingegen nicht.
Und auch der Zugriff per Reflexion gestaltet sich unterschiedlich, aber wer so tief einsteigt, sollte wohl sowieso genau wissen, was er tut.
13.04.2012
Matthias Hlawatsch 13,2k 4 9
Thumb up! Gut erklärt!
Eiger 13.04.2012
+1 Sehr gut erklärt. Zusammen mit Xantiva's Tip eine runde Sache.
ffordermaier 13.04.2012
Freut mich, dass diese Antwort so viel Zuspruch gefunden hat. Danke an alle, die das mit einem Klick an die richtige Stelle ;-) zum Ausdruck gebracht haben.
In der aktuellen dotnetpro (5/2012) wird das Thema von Golo Roden in seiner Kolumne "Scharfes C" behandelt. Er liefert noch ein paar weitere Argumente "pro Property". Eins davon habe ich als Update bzw. Korrektur noch mit in meine Antwort übernommen.
Matthias Hlawatsch 21.04.2012
8
Wenn alle so schön die "Kurzschreibweise" bewerben, möchte ich aber auf ein großes Problem damit hinweisen:

Wenn die Klasse jemals binär serialisiert werden soll, dann sollte man niemals die Kurzschreibweise einsetzen. Hier ist das Problem beschrieben:

http://codekicker.de/fragen/geht-binaerer-Serialisierung-Nachtraegliche-Aenderungen-Property

In Kurzform: Wenn man jemals von der Kurzform weg muss, weil im setter z. B. etwas geprüft werden soll, dann sind die Daten weg (können nicht mehr deserialisiert werden)! Bei Serialisierung also immer mit einem privaten Feld arbeiten.

Ciao,
Mike
13.04.2012
Xantiva 2,3k 2 9
Xantiva 2,3k 2 9
+1 guter Hinweis
Matthias Hlawatsch 13.04.2012
Nochmal +1. Der Tip hat mir beim letzten Mal schon geholfen.
ffordermaier 13.04.2012
+1 Guter Hinweis
multi1209 13.04.2012
3
Als Erstes:
Für die zweite Variante gibt es auch die Möglichkeit "auto properties" zu verwenden. Das sieht dann folgendermaßen aus:
public string Name { get; set; }

Die wesentlichen Unterschiede zu einem Feld sind:

  • Du kannst den getter sowie den setter als private kennzeichnen.
  • Properties können in Interfaces verwendet werden, Felder nicht.
13.04.2012
Martin Fuchs 1,4k 9
2
Bei public-Feldern würde ich immer Properties verwenden mit Getter/Setter. Bei späteren Erweiterungen hat man damit einfach die bessere Kontrolle drüber.

Vor allem wenn die Klasse aus anderen Programmen heraus genutzt wird, kann man ein Feld nicht einfach so in ein Property verändern, ohne das aufrufende Programm neu zu kompilieren. Alleine schon deswegen würde ich immer Properties verwenden, wenn es public ist.

Es gibt noch die Kurzform für Auto-Implemented Properties:

class Klasse2
{
public string Name { get; set; }
}


C# erzeugt dann das private Backingfield automatisch, ohne dass Du Dich drum kümmern musst.

Weiterer Vorteil: Mit Getter/Setter kannst Du festlegen, wer ändern und lesen darf, etwa per:


class Klasse2
{
public string Name { get; private set; }
}


Damit darf der Wert nur aus der Klasse selbst heraus geändert werden, gelesen werden darf es aber auch von "außen".

Grundregel: Aus einer Klasse immer nur das nach außen sichtbar und änderbar machen, was UNBEDINGT notwendig ist, aber nicht mehr!
13.04.2012
commänder 420 1 7
0
So direkt, also wie du es gerade hast, existiert (aus meiner Sicht) überhaupt kein Unterschied.

Wenn du jedoch willst, dass Validierungen beim Setzen oder Auslesen von Variablen gemacht werden oder wenn du den Wert ReadOnly haben willst, wirst du um die Variante wie in Klasse2 zu sehen (Also die Verwendung von Properties) nicht mehr herumkommen.

so far
Karill Endusa
13.04.2012
Karill Endusa 1,5k 1 9
0
Gute Frage, beides sind ja reine Datenklassen (im Prinzip nichts anderes als Records) und in der von dir vorgestellten Implementierung, hat der Propertyzugriff über get/set keinerlei Vorteil. Eher einen Nachteil (mehr Schreibaufwand) und vielleicht sogar schlechtere Performance?
13.04.2012
m.fuchs 1,8k 2 8

Stelle deine .net-Frage jetzt!