在c#构造函数初始化中使用默认属性值

本文关键字:默认 属性 构造函数 初始化 | 更新日期: 2023-09-27 18:05:54

考虑以下类:

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

这段代码:

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

显然,执行这段代码后,Bar的值将变为null(假设bar = null)。

我希望构造函数初始化器在给定情况下使用默认属性值(例如,当barnull时)。我想知道是否有更简单的方法来做到这一点,而不是使用:

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

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

在c#构造函数初始化中使用默认属性值

你可以通过使用空合并运算符来简化它:

  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,它的值将在属性的setter中被忽略。

最简单和最易读的解决方案是:

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

没有办法像你在初始化器中建议的那样进行验证(至少在c# 6中没有)。你可以使用一些结构来提取你的默认值为常量,就像这里的其他答案所建议的那样,但这会降低可读性,并且不会使使用类更容易-你必须了解实现(常量中的默认值)细节,这会破坏封装。

如果你主要关心的是代码风格,我建议你习惯if s,因为它们没有什么问题,而且对于维护你的代码的其他人或你自己来说,它们很容易理解。

如果你还需要其他的东西,比如属性值的验证,你需要把它放在setter本身中(你应该在问题中说明)。

最干净的OO方法是使用重载构造函数和工厂方法:

    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; }
    }

如果您将Bar属性的默认值提取到static字段:

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

你可以这样做:

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

可以做:

class Foo
{
    public const string BarDefault = "foobar";
    public string Bar { get; set; } = BarDefault;
}
var foo = new Foo { Bar = bar ?? Foo.BarDefault };

它的优点是在类的顶部拥有所有const中的默认值,但我个人并不认为这有什么意义。然而,这并不意味着你不需要条件语句。