Рассмотрим следующий класс:

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

И этот фрагмент кода:

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

Очевидно, что значение Bar будет null после выполнения этого кода (предположим, что bar = null).

Я хочу, чтобы инициализатор конструктора использовал значение свойства по умолчанию в определенных случаях (например, когда bar равно null). Я хочу знать, есть ли более простой способ сделать это вместо использования:

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

Или же

foo = new Foo();
if (bar != null)
    foo.Bar = bar;
c#
3
danrah 7 Сен 2016 в 10:38

5 ответов

Лучший ответ

Что ж, вы можете упростить это, используя нулевой оператор объединения:

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

Или вы можете изменить свойство, чтобы проверять нулевые значения и игнорировать их:

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

Затем вы можете использовать этот код для создания экземпляра Foo:

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

Обратите внимание, что теперь, если bar имеет значение NULL, его значение будет игнорироваться в установщике свойства.

2
Fabjan 7 Сен 2016 в 12:52

Самым простым и читаемым (IMHO) решением было бы:

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

Невозможно выполнить проверку, как вы предложили в инициализаторе (по крайней мере, не в C # 6). Вы можете использовать некоторые конструкции с извлечением значения по умолчанию для константы, как предлагают другие ответы здесь, но это снижает удобочитаемость и не упрощает использование класса - вы должны знать детали реализации (значение по умолчанию в константе), что нарушает инкапсуляция.

Если вас больше всего беспокоит стиль кода, я предлагаю вам привыкнуть к if, потому что в них нет ничего плохого и их легко понять кому-то другому, обслуживающему ваш код или вам самому, через несколько месяцев.

Если вам нужно что-то еще, например, проверка значения свойства, вам нужно поместить его в сам сеттер (и вы должны были указать это в вопросе).

1
slawekwin 7 Сен 2016 в 08:07

Если вы извлечете значение свойства Bar по умолчанию в поле static:

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

    public static string defaultBarValue = "foobar";
}

Вы сможете это сделать:

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

Но я сомневаюсь, что это того стоит ...

0
haim770 7 Сен 2016 в 07:55

Самый чистый объектно-ориентированный способ сделать это - использовать перегруженный конструктор и фабричный метод:

    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; }
    }
1
George Mamaladze 7 Сен 2016 в 09:30

Вы могли бы сделать:

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

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

У него есть преимущество в том, что все ваши значения по умолчанию находятся в consts в верхней части класса, но лично я не вижу в этом смысла. Однако это означает, что вам не нужен условный оператор (вроде).

0
webnoob 7 Сен 2016 в 07:56