我想让我的课堂不变.显而易见的方法是将所有字段声明为get; private set;并初始化构造函数中的所有字段.所以客户必须在构造函数中提供所有内容 问题是,当构造函数中有大约10个或更多字段传递它们变得非常难以理解时,因为每个字段都没有标签.
例如,这很可读:
info = new StockInfo
{
Name = data[0] as string,
Status = s,
LotSize = (int)data[1],
ISIN = data[2] as string,
MinStep = (decimal)data[3]
};
Run Code Online (Sandbox Code Playgroud)
与此相比:
new StockInfo(data[0] as string, s, (int) data[1], data[2] as string, (decimal) data[3])
Run Code Online (Sandbox Code Playgroud)
现在成像我有10个或更多参数.
那么如何才能使类不可变保存可读性?
我建议只在使用构造函数时使用相同的格式:
info = new StockInfo(
data[0] as string, // Name
s, // Status
(int)data[1], // LotSize
data[2] as string, // ISIN
(decimal)data[3] // MinStep
);
Run Code Online (Sandbox Code Playgroud)
你能提出更好的建议吗?
以下是使用C#命名参数的方法:
var info = new StockInfo
(
Name: data[0] as string,
Status: s,
LotSize: (int)data[1],
ISIN: data[2] as string,
MinStep: (decimal)data[3]
);
Run Code Online (Sandbox Code Playgroud)
这里有一些选择.你必须决定什么是最适合你的:
使用带有命名参数的经典不可变对象(带有大量构造函数)以提高可读性.(缺点:有些人不赞成使用许多构造函数参数.如果不支持命名参数,可能不方便使用其他.NET语言.)
info = new StockInfo
(
name: data[0] as string,
status: s,
...
)
Run Code Online (Sandbox Code Playgroud)
通过不可变接口公开可变对象.(缺点:对象仍然可以通过强制转换进行变异.要写入额外的类型.)
public interface IStockInfo
{
string Name { get; }
string Status { get; }
}
IStockInfo info = new StockInfo
{
Name = data[0] as string,
Status = s,
...
}
Run Code Online (Sandbox Code Playgroud)
公开可变对象的只读视图 - ReadOnlyCollection<T>例如,参见.(缺点:实现额外的类型.创建额外的对象.额外的间接.)
var readOnlyInfo = new ReadOnlyStockInfoDecorator(info);
Run Code Online (Sandbox Code Playgroud)
公开可变对象的不可变克隆.(缺点:要实现的额外类型.创建了额外的对象.需要复制.)
var immutableInfo = new ImmutableStockInfo(info);
Run Code Online (Sandbox Code Playgroud)
使用freezable对象.(缺点:冻结后突变 - 尝试在执行时才会被捕获.)
info.Freeze();
info.Name = "Test"; // Make this throw an exception.
Run Code Online (Sandbox Code Playgroud)
使用流畅式的构建器或类似的(缺点:有些人可能不熟悉模式.需要编写大量额外代码.创建了大量副本.中间状态可能是非法的)
info = StockInfo.FromName(data[0] as string)
.WithStatus(s) // Make this create a modified copy
.WithXXX() ;
Run Code Online (Sandbox Code Playgroud)