2016-09-07 3 views
3

die folgende Klasse vor:Verwendung Standardeigenschaft Wert in C# Konstruktor initializer

class Foo 
{ 
    public string Bar { get; set; } = "foobar"; 
} 

Und dieses Stück Code:

var foo = new Foo { 
    Bar = bar == null 
      ? null 
      : bar 
}; 

Offensichtlich ist der Wert von Barnull nach der Ausführung sein würde Code (angenommen, dass bar = null).

Ich möchte, dass der Konstruktorinitialisierer in bestimmten Fällen den Standardeigenschaftswert verwendet (z. B. wenn barnull ist). Ich möchte wissen, ob es ein einfacherer Weg, dies zu tun statt mit:

if (bar == null) { 
    foo = new Foo(); 
} else { 
    foo = new Foo { Bar = bar }; 
} 

Oder

foo = new Foo(); 
if (bar != null) 
    foo.Bar = bar; 
+0

einfach nicht belegen den Wert? 'if (bar! = null) {...}' –

+0

@ LasseV.Karlsen wäre die bedingte Anweisung komplex, wenn die Anzahl der Parameter zunimmt. – danrah

+0

Mögliches Duplikat von [Objektinitialisierer und dynamisch spezifizierende Eigenschaften] (http://stackoverflow.com/questions/2234091/object-initializer-and-dynamically-specifying-properties) – slawekwin

Antwort

2

Nun, können Sie es mithilfe von null Koaleszierstruktur Betreiber vereinfachen:

var foo = new Foo(); 
    foo.Bar = bar ?? foo.Bar; 

Oder Sie können Eigenschaft ändern für NULL-Werte zu überprüfen und sie ignorieren:

private string _bar = "foobar"; 
    public string Bar 
    { 
     get { return _bar; } 
     set { _bar = value ?? _bar; } 
    } 

Dann können Sie diesen Code verwenden Foo zu instanziiert:

var foo = new Foo() { Bar = bar }; 

Beachten Sie, dass jetzt, wenn bar ist null, sein Wert wird im Setter der Eigenschaft ignoriert.

1

Einfachste und lesbar (IMHO) Lösung wäre:

var foo = new Foo(); 
if (bar != null) 
    foo.Bar = bar; 

Es gibt keine Möglichkeit, die Validierung wie im Initialisierer vorgeschlagen zu machen (zumindest nicht wie in C# 6). Sie könnten einige Konstrukte verwenden, um Ihren Standard auf die Konstante zu extrahieren, wie andere hier vorgeschlagene Antworten, aber das entzieht der Lesbarkeit und macht die Verwendung der Klasse nicht einfacher - Sie müssen etwas über die Implementierung (Standardwert in der Konstante) Details wissen, die die bricht Verkapselung.

Wenn Ihr Hauptanliegen ist über Code-Stil, ich schlage vor, Sie gewöhnen sich an if s, denn es ist nichts falsch mit ihnen und sind leicht zu verstehen für jemand anderen Wartung Ihres Codes oder sich in ein paar Monaten.

Wenn Sie noch etwas anderes benötigen, wie die Validierung des Eigenschaftswerts, müssen Sie es in den Setter selbst einfügen (und Sie sollten dies in der Frage angegeben haben).

+0

Ja, das ist richtig, aber ich wollte wissen, ob es solche Features gibt, um bedingte Anweisungen zu vermeiden – danrah

+0

@danrah Gibt es (noch nicht?). Es sei denn, Sie können die automatische Eigenschaft ändern, um das 'if' dort zu machen. – slawekwin

+1

@danrah Warum? Welches Problem versuchen Sie zu lösen? – Luaan

0

Du könnte tun:

class Foo 
{ 
    public const string BarDefault = "foobar"; 
    public string Bar { get; set; } = BarDefault; 
} 

var foo = new Foo { Bar = bar ?? Foo.BarDefault }; 

es einen Vorteil, der mit allen Ihren Vorgaben in consts an der Spitze der Klasse hat, aber ich weiß nicht wirklich den Punkt persönlich sehen. Es bedeutet jedoch, dass Sie keine bedingte Aussage (Art von) benötigen.

0

Wenn Sie den Standardwert der Bar Eigenschaft auf einen static Feld extrahieren:

public class Foo 
{ 
    public string Bar { get; set; } = defaultBarValue; 

    public static string defaultBarValue = "foobar"; 
} 

Sie werden in der Lage sein, dies zu tun:

new Foo 
{ 
    Bar = bar != null ? bar : Foo.defaultBarValue, 
}; 

Aber ich bezweifle, dass es sich lohnt, die Anstrengung...

+0

Oder einfach: 'new Foo {Bar = bar ?? Foo.defaultBarValue,} ' –

+0

Oder nur' Bar = bar ?? "foobar" '. Wenn der * Aufrufer * den Wert validieren muss, spielt es keine Rolle, ob Sie ein statisches Feld, eine Konstante oder eine fest codierte Zeichenfolge verwenden. Die Validierungslogik ist bereits durchgelaufen –

+0

@OrkhanAlikhanov, True. Aber ich wollte die gleichen Konstrukte wie das OP verwenden. – haim770

1

Die sauberste OO Art und Weise, dies zu tun, indem Sie überladenen Konstruktor und eine Factory-Methode wäre:

dann
class Foo 
    { 
     public Foo Create(string bar) 
     { 
      return bar == null ? new Foo() : new Foo(bar); 
     } 

     public Foo() : this("foobar") 
     { 
     } 

     public Foo(string bar) 
     { 
      Bar = bar; 
     } 
     public string Bar { get; } 
    }