不可变类型构造函数的简写

时间:2016-05-28 22:19:57

标签: c#

我在C#中有一些不可变类型。他们基本上就是这样。

public class Class : IInterface
{
    public Class(IInterface2 prop1, IInterface2 prop2)
    {
        Property1 = prop1;
        Property2 = prop2;
    }

    public IInterface2 Property1 { get; }
    public IInterface2 Property2 { get; }
}

我刚刚发现一个错误,其中构造函数中的两个属性集混淆了。

C#中的不可变类型是否有任何缩写可以省略或生成此构造函数?

我试过,例如

public class Class : IInterface
{
    public readonly IInterface2 Property1;
    public readonly IInterface2 Property2;
}

不幸的是,当我尝试使用它时,例如

var f = new Class { Property1 = null, Property2 = null };

编译器对我大喊大叫,说除了构造函数或变量初始值设定项之外,不能设置只读字段,尽管它显然是一个该死的变量初始化器。

3 个答案:

答案 0 :(得分:2)

不,C#中没有允许从类外部设置只读属性或自动生成构造函数的语法。

初始化器语法只是属性集调用的语法糖 - 所以这是预期的行为而不是规范中的疏忽。这在Readonly field in object initializer问题和MSDN文章中讨论过:

Object and Collection Initializers (C# Programming Guide)

  

对象初始值设定项允许您在创建时为任何可访问字段或对象属性赋值,而无需调用构造函数,后跟赋值语句行

答案 1 :(得分:1)

  

“除了构造函数或变量之外,不能设置只读字段   初始化程序,尽管它显然是一个该死的变量   初始值设定“。

不,不是。 “变量初始化程序”就是这样:

public class Class
{
    public int Property1 { get; } = 5;
}

= 5”是变量初始值设定项,因为您只是在定义的同一位置初始化变量。

请参阅this article

你所谓的“变量初始值设定项”实际上是“对象初始值设定项”,这只是语法糖:

  1. 调用构造函数
  2. 在构造函数外部设置属性列表。
  3. 例如:

    var c = new Class("hello", 4.5) //<-- this is the constructor
    {
        Prop1 = new DataTable(),  //<-- from here you're outside the constructor,
        Prop2 = new Point(2,3),   //    so you can't set an only "{ get; }" property.
        Prop3 = 0.2,
    };
    

答案 2 :(得分:1)

如果我理解正确,你想要能够初始化只读字段的原因是为了避免混淆,其中以错误的顺序调用具有两个兼容类型的构造函数,对吧?

因此,虽然其他问题很好地解释了为什么目前无法实现这一点,但是仍然可以使用一种有用的技术来最小化此问题,同时仍然使用相同的构造函数 - named arguments。 C#允许您显式声明参数的名称,然后以任何顺序指定它们:

var myClass = new Class(prop2: interface2Instance, prop1: interface1Instance);

这将编译,并明确将值传递给哪个参数。

当然,您无法在代码本身中强制执行此要求,但如果您发现许多构造函数具有需要澄清的兼容类型,则它可以成为您的编码样式指南的一部分