考虑以下未编译的代码片段。
class Class
{
public double Value { get; set; }
public int Frequency { get; set; }
}
class BoxAndWhisker
{
private readonly List<Class> _classes = new List<Class>();
public BoxAndWhisker()
{
Classes = _classes.AsReadOnly();
}
public IReadOnlyList<Class> Classes { get; }
}
class Program
{
static void Main(string[] args)
{
BoxAndWhisker baw = new BoxAndWhisker
{
Classes =
{
new Class{ Value=1,Frequency=20},
new Class{Value=2,Frequency=10}
}
};
}
}
我希望属性Classes
在baw
安装后立即只读。如何做到这一点?换句话说,Classes
在对象初始值设定项中必须是可写的,但在其他地方必须是只读的。
编辑
比起参数化构造函数,我更喜欢对象初始化器。
为什么不通过构造函数传递Class
es?例如
class BoxAndWhisker {
public BoxAndWhisker(params Class[] items) {
Classes = null != items
? new List<Class>(items).AsReadOnly()
: throw new ArgumentNullException(nameof(items));
}
public IReadOnlyList<Class> Classes { get; }
}
然后
static void Main(string[] args)
{
BoxAndWhisker baw = new BoxAndWhisker(
new Class { Value = 1, Frequency = 20 },
new Class { Value = 2, Frequency = 10 }
);
...
}
删除
set;
从内的属性
类
并使类具有一个构造函数,该构造函数设置属性的初始值,因此不能覆盖/更改
你可以在文档中阅读:
对象初始化器语法允许您创建一个实例,然后将新创建的对象及其分配的属性分配给分配中的变量。
因此:
var foo = new Bar { Baz = "baz" };
完全等同于:
var temp = new Bar();
temp.Baz = "baz";
var foo = temp;
因此,您不能以自己想要的方式限制属性分配。唯一的解决方案是使用其他答案中提出的构造函数。
将IList<Class>
实例传递给BoxAndWhisker
构造函数,并维护支持IReadOnlyList<Class>
的属性
class BoxAndWhisker
{
public BoxAndWhisker(IList<Class> classes)
{
if (classes == null)
throw new ArgumentNullException(nameof(classes));
Classes = new ReadOnlyCollection<Class>(classes);
}
public IReadOnlyList<Class> Classes { get; }
}
的使用示例
BoxAndWhisker baw = new BoxAndWhisker(new List<Class>
{
new Class {Value = 1, Frequency = 20},
new Class {Value = 2, Frequency = 10}
});