10 Stimmen

C#-Äquivalent für C++-Makros und Verwendung von Auto<>-Eigenschaften

Ich habe einige Auto-Instantiation-Code, die ich auf etwa 15 Eigenschaften in einer ziemlich großen Klasse anwenden möchte. Der Code ist ähnlich wie der folgende, aber die Typ ist anders für jede Instanz:

protected ComplexType _propertyName;
public ComplexType PropertyName
{
    get
    {
        if (_propertyName == null) {
            _propertyName = new ComplexType();
        }

        return _propertyName;
    }
}

Um dies in C++ zu wiederholen (da es ~15 Instanzen gibt), hätte ich eine Präprozessormakro aber ich habe festgestellt, dass C# sie nicht unterstützt.

Ich frage mich, wenn jemand eine Empfehlung, wie man dies sauber in C# tun hat?

22voto

Charlie Punkte 10070

Dies könnte die Dinge etwas übersichtlicher machen, Sie könnten diese Methode hinzufügen, um eine gewisse Wiederverwendung einzuführen:

protected ComplexType _propertyName;
public ComplexType PropertyName
{
    get
    {
        return GetProperty(ref _propertyName);
    }
}
.
.
private T GetProperty<T>(ref T property) where T : new()
{
  if (property == null)
    property = new T();
  return property;
}

16voto

Martin Liversage Punkte 100306

Sie können die ?? Operator, um den Code in einer Zeile zu vereinfachen:

protected ComplexType _propertyName;
public ComplexType PropertyName
{
  get
  {
    return _propertyName ?? (_propertyName = new ComplexType());
  }
}

Nebenbei bemerkt würde ich geschützte Felder wahrscheinlich vermeiden. Wenn Sie die Eigenschaft aus einer abgeleiteten Klasse festlegen müssen, würde ich eher einen geschützten Setter erstellen.

1 Stimmen

Aus meiner Erfahrung in C++ habe ich die Erfahrung gemacht, dass es besser ist, alles auf "protected" statt auf "private" zu setzen, wenn Sie Ihre Anwendung zukunftssicher machen wollen, ohne den Mitgliederschutz aufzugeben. Ich verwende selten private.

2 Stimmen

@Kelix: Aber Sie geben den Mitgliederschutz auf, indem Sie die Felder schützen. Jetzt hat jede abgeleitete Klasse vollen Zugriff auf Ihre Felder. Das ist ähnlich wie bei öffentlichen Feldern, nur dass nur abgeleitete Klassen und nicht alle Klassen auf die Felder zugreifen können.

0 Stimmen

@Martin: Ja, das ist der gewünschte Effekt. Es sei denn, ich möchte den Zugriff in abgeleiteten Klassen explizit nicht zulassen, dann werde ich sie als "geschützt" markieren. Wenn man sich die Mühe macht, eine Klasse abzuleiten, möchte man in der Regel ohnehin das Verhalten in irgendeiner Weise ergänzen oder ändern, warum also nicht den uneingeschränkten Zugriff darauf ermöglichen? Wenn es sich um eine öffentlich zugängliche Schnittstelle handelt (z. B. eine Klassenbibliothek), wäre "private" natürlich viel besser geeignet. Ich mag es einfach nicht, den Zugriff einzuschränken, wenn es nicht notwendig ist.

11voto

Guffa Punkte 663241

Sie können eine generische Struktur erstellen, die die faule Erstellung übernimmt:

public struct LazyCreate<T> where T : class, new() {
   private T _value;
   public T Value {
      get {
         if (_value == null) {
            _value = new T();
         }
         return _value;
      }
   }
}

protected LazyCreate<ComplexType> _propertyName;
public ComplexType PropertyName {
    get {
        return _propertyName.Value;
    }
}

1 Stimmen

Ich würde bei Verwendung einer generischen Struktur verwenden, um zu vermeiden, dass mehr Objekte auf dem Heap erstellt werden.

0 Stimmen

Was passiert, wenn T ein struct ist? new() schließt das nicht aus, und AFAIK können structs nicht null sein. :)

0 Stimmen

@Rytmis: Um mit Strukturen umzugehen, müsste es ein separates Flag geben, das anzeigt, ob der Wert erstellt wurde oder nicht, aber eine faule Initialisierung für Strukturen scheint generell eine schlechte Design-Entscheidung zu sein... Ich werde eine Einschränkung hinzufügen, so dass es nur mit Referenztypen verwendet werden kann.

6voto

Thomas Levesque Punkte 277723

Auch wenn es Ihr Problem nicht direkt löst, könnten Sie einen Blick auf das neue Lazy<T> Klasse, die mit .NET 4.0 ausgeliefert wird. Sie ist speziell für träge Initialisierungsszenarien konzipiert.

2voto

Peter Mortensen Punkte 29848

Sie könnten die viel übersehene T4 (Textvorlage Transformation Toolkit), um den Code zu erzeugen. Es ist enthalten mit Visual Studio 2008.

Es gab 2009-06 eine .NET Rocks-Folge darüber: " Peter Vogel verwendet Code Generation " .

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