104 Stimmen

Warum sollte ich die Verwendung von Eigenschaften in C# vermeiden?

In seinem hervorragenden Buch CLR Via C# sagt Jeffrey Richter, dass er Eigenschaften nicht mag und empfiehlt, sie nicht zu verwenden. Er gab einige Gründe an, aber ich verstehe sie nicht wirklich. Kann mir jemand erklären, warum ich Eigenschaften verwenden sollte oder nicht? Ändert sich das in C# 3.0, mit automatischen Eigenschaften?

Als Referenz habe ich die Stellungnahmen von Jeffrey Richter hinzugefügt:

- Eine Eigenschaft kann schreibgeschützt oder schreibgeschützt sein; der Feldzugriff ist immer lesbar und schreibbar. Wenn Sie eine Eigenschaft definieren, ist es am besten, sowohl Get- als auch Set-Accessor-Methoden anzubieten.

- Eine Eigenschaftsmethode kann eine Ausnahme auslösen; ein Feldzugriff löst nie eine Ausnahme aus.

- Eine Eigenschaft kann nicht als out- oder ref-Parameter an eine Methode übergeben werden, ein Feld schon. Für Beispiel: Der folgende Code lässt sich nicht kompilieren:

using System;
public sealed class SomeType
{
   private static String Name 
   {
     get { return null; }
     set {}
   }
   static void MethodWithOutParam(out String n) { n = null; }
   public static void Main()
   {
      // For the line of code below, the C# compiler emits the following:
      // error CS0206: A property or indexer may not
      // be passed as an out or ref parameter
      MethodWithOutParam(out Name);
   }
}

- Die Ausführung einer Eigenschaftsmethode kann lange dauern; der Feldzugriff wird immer sofort abgeschlossen. Ein häufiger Grund für die Verwendung von Eigenschaften ist die Synchronisierung von Threads, die den Thread für immer anhalten kann. Daher sollte eine Eigenschaft nicht verwendet werden, wenn eine Thread-Synchronisierung erforderlich ist. In dieser Situation ist eine Methode vorzuziehen. Wenn auf Ihre Klasse auch aus der Ferne zugegriffen werden kann auf Ihre Klasse aus der Ferne zugegriffen werden kann (z. B. wenn Ihre Klasse von System.MashalByRefObject abgeleitet ist), wird der Aufruf der Eigenschaftsmethode sehr langsam sein, und daher ist eine Methode einer Eigenschaft. Meiner Meinung nach sollten von MarshalByRefObject abgeleitete Klassen niemals Eigenschaften verwenden.

- Wenn eine Eigenschaftsmethode mehrmals hintereinander aufgerufen wird, kann sie jedes Mal einen anderen Wert zurückgeben jedes Mal einen anderen Wert zurückgeben; ein Feld gibt jedes Mal denselben Wert zurück. Die Klasse System.DateTime hat eine schreibgeschützte Now-Eigenschaft, die das aktuelle Datum und die aktuelle Uhrzeit zurückgibt. Jedes Mal, wenn Sie diese Eigenschaft abfragen, wird ein anderer Wert zurückgegeben. Dies ist ein Fehler, und Microsoft wünscht, dass sie die Klasse reparieren könnte, indem sie Now zu einer Methode statt zu einer Eigenschaft macht.

- Eine Eigenschaftsmethode kann beobachtbare Nebeneffekte haben, ein Feldzugriff hat das nie. In anderen Ein Benutzer eines Typs sollte also in der Lage sein, verschiedene von einem Typ definierte Eigenschaften in beliebiger Reihenfolge zu setzen, ohne ein anderes Verhalten des Typs zu bemerken.

- Eine Eigenschaftsmethode kann zusätzlichen Speicher benötigen oder einen Verweis auf etwas zurückgeben zurück, das eigentlich nicht zum Zustand des Objekts gehört, so dass eine Änderung des zurückgegebenen Objekts keine Auswirkungen auf das ursprüngliche Objekt; die Abfrage eines Feldes gibt immer einen Verweis auf ein Objekt zurück, das garantiert Teil des Zustands des ursprünglichen Objekts ist. Die Arbeit mit einer Eigenschaft, die eine Kopie zurückgibt, kann für Entwickler sehr verwirrend sein, und diese Eigenschaft ist häufig nicht dokumentiert.

11 Stimmen

Ich besitze die 3. Auflage von "CLR via C#" und auf Seite 242 sagt Herr Richter, dass er persönlich keine Eigenschaften mag, aber er empfiehlt nie, sie nicht zu verwenden. Bitte geben Sie die Buchversion und die Seitenzahl an, wo Sie dies gelesen haben.

9voto

Mark Simpson Punkte 22759

Das ist nur die Meinung einer Person. Ich habe ziemlich viele c#-Bücher gelesen und ich habe noch niemanden gesehen, der sagt "don't use properties".

Ich persönlich denke, Eigenschaften sind eines der besten Dinge über c#. Sie ermöglichen es Ihnen, Zustand über was auch immer Mechanismus, den Sie mögen auszusetzen. Sie können faul instanziieren, wenn etwas zum ersten Mal verwendet wird, und Sie können die Validierung beim Setzen eines Wertes usw. durchführen. Wenn ich sie verwende und schreibe, betrachte ich Eigenschaften einfach als Setter und Getter, was eine viel schönere Syntax ist.

Was die Vorbehalte gegenüber Immobilien betrifft, so gibt es einige. Eine ist wahrscheinlich ein Missbrauch von Eigenschaften, die andere kann subtil sein.

Erstens: Eigenschaften sind Arten von Methoden. Es kann überraschen, wenn Sie eine komplizierte Logik in einer Eigenschaft unterbringen, weil die meisten Benutzer einer Klasse erwarten, dass die Eigenschaft relativ leicht ist.

z.B.

public class WorkerUsingMethod
{
   // Explicitly obvious that calculation is being done here
   public int CalculateResult()
   { 
      return ExpensiveLongRunningCalculation();
   }
}

public class WorkerUsingProperty
{
   // Not at all obvious.  Looks like it may just be returning a cached result.
   public int Result
   {
       get { return ExpensiveLongRunningCalculation(); }
   }
}

Ich finde, dass die Verwendung von Methoden für diese Fälle hilft, eine Unterscheidung zu treffen.

Zweitens, und das ist noch wichtiger, können Eigenschaften Nebeneffekte haben, wenn Sie sie während des Debuggens auswerten.

Nehmen wir an, Sie haben eine Eigenschaft wie diese:

public int Result 
{ 
   get 
   { 
       m_numberQueries++; 
       return m_result; 
   } 
}

Nehmen wir an, Sie haben eine Ausnahme, die auftritt, wenn zu viele Abfragen gemacht werden. Raten Sie mal, was passiert, wenn Sie mit dem Debugging beginnen und die Eigenschaft im Debugger überfliegen? Schlimme Dinge. Vermeiden Sie dies! Wenn Sie sich die Eigenschaft ansehen, ändert sich der Zustand des Programms.

Das sind die einzigen Vorbehalte, die ich habe. Ich denke, dass die Vorteile von Immobilien die Probleme bei weitem überwiegen.

6voto

Rashack Punkte 4638

Dieser Grund muss in einem ganz bestimmten Zusammenhang gegeben worden sein. Normalerweise ist es umgekehrt - es wird empfohlen, Eigenschaften zu verwenden, da sie eine Abstraktionsebene darstellen, die es Ihnen ermöglicht, das Verhalten einer Klasse zu ändern, ohne ihre Clients zu beeinflussen...

6voto

Cecil Has a Name Punkte 4862

Ich kann nicht umhin, mich mit den Einzelheiten der Stellungnahmen von Jeffrey Richter zu befassen:

Eine Eigenschaft kann schreibgeschützt oder schreibgeschützt sein; der Feldzugriff ist immer lesbar und schreibbar.

Falsch: Felder können als schreibgeschützt markiert werden, so dass nur der Konstruktor des Objekts in sie schreiben kann.

Eine Eigenschaftsmethode kann eine Ausnahme auslösen; ein Feldzugriff löst nie eine Ausnahme aus.

Falsch: Die Implementierung einer Klasse kann den Zugriffsmodifikator eines Feldes von öffentlich auf privat ändern. Der Versuch, private Felder zur Laufzeit zu lesen, führt immer zu einer Ausnahme.

5voto

M4N Punkte 92235

Ich stimme nicht mit Jeffrey Richter überein, aber ich kann mir denken, warum er die Eigenschaften nicht mag (ich habe sein Buch nicht gelesen).

Auch wenn Eigenschaften genau wie Methoden (von der Implementierung her) sind, erwarte ich als Benutzer einer Klasse, dass sich ihre Eigenschaften "mehr oder weniger" wie ein öffentliches Feld verhalten, z. B:

  • es gibt keine zeitaufwändige Operation innerhalb der Eigenschaft Getter/Setter
  • der Property Getter hat keine Nebeneffekte (mehrfacher Aufruf ändert das Ergebnis nicht)

Leider habe ich Immobilien gesehen, die sich nicht so verhalten haben. Aber das Problem sind nicht die Eigenschaften selbst, sondern die Leute, die sie implementiert haben. Es braucht also nur etwas Aufklärung.

5voto

milleniumbug Punkte 15053

Das Argument geht davon aus, dass Eigenschaften schlecht sind, weil sie wie Felder aussehen, aber überraschende Aktionen ausführen können. Diese Annahme wird durch die Erwartungen der .NET-Programmierer widerlegt:

Eigenschaften sehen nicht wie Felder aus. Felder sehen wie Eigenschaften aus.

- Eine Eigenschaftsmethode kann eine Ausnahme auslösen; ein Feldzugriff löst nie eine Ausnahme aus.

Ein Feld ist also wie eine Eigenschaft, die garantiert nie eine Ausnahme auslöst.

- Eine Eigenschaft kann nicht als out- oder ref-Parameter an eine Methode übergeben werden, ein Feld schon.

Ein Feld ist also wie eine Eigenschaft, aber es hat zusätzliche Fähigkeiten: die Übergabe an eine ref / out Methoden zu akzeptieren.

- Die Ausführung einer Eigenschaftsmethode kann lange dauern; der Feldzugriff wird immer sofort abgeschlossen. [...]

Ein Feld ist also wie eine schnelle Eigenschaft.

- Wenn eine Eigenschaftsmethode mehrmals hintereinander aufgerufen wird, kann sie jedes Mal einen anderen Wert zurückgeben; ein Feld gibt jedes Mal denselben Wert zurück. Die Klasse System.DateTime hat eine schreibgeschützte Now-Eigenschaft, die das aktuelle Datum und die aktuelle Uhrzeit zurückgibt.

Ein Feld ist also wie eine Eigenschaft, die garantiert denselben Wert zurückgibt, es sei denn, das Feld wurde auf einen anderen Wert gesetzt.

- Eine Eigenschaftsmethode kann beobachtbare Nebeneffekte verursachen, ein Feldzugriff tut dies nie.

Auch hier ist ein Feld eine Eigenschaft, bei der dies garantiert nicht der Fall ist.

- Eine Eigenschaftsmethode kann zusätzlichen Speicher benötigen oder einen Verweis auf etwas zurückgeben, das nicht zum Zustand des Objekts gehört, so dass die Änderung des zurückgegebenen Objekts keine Auswirkungen auf das ursprüngliche Objekt hat; die Abfrage eines Feldes gibt immer einen Verweis auf ein Objekt zurück, das garantiert zum Zustand des ursprünglichen Objekts gehört. Die Arbeit mit einer Eigenschaft, die eine Kopie zurückgibt, kann für Entwickler sehr verwirrend sein, und diese Eigenschaft ist häufig nicht dokumentiert.

Dies mag überraschen, aber nicht, weil es sich um eine Immobilie handelt, die dies tut. Vielmehr ist es, dass kaum jemand veränderbare Kopien in Eigenschaften zurückgibt, so dass dieser 0,1 % Fall überraschend ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X