C# 使用可变对象作为构造函数参数
将对象作为构造函数参数传递的最佳实践是什么?传递可变对象可能导致意外结果 一个简单的例子。我们期望有200个,但是调用TestMethod()会得到10000个: 选项3。修复类C# 使用可变对象作为构造函数参数,c#,design-patterns,C#,Design Patterns,将对象作为构造函数参数传递的最佳实践是什么?传递可变对象可能导致意外结果 一个简单的例子。我们期望有200个,但是调用TestMethod()会得到10000个: 选项3。修复类某些度量值-使其不可变: public class SomeMeasurements { public SomeMeasurements(int width, int height) { Width = width; Height = height; }
某些度量值
-使其不可变:
public class SomeMeasurements
{
public SomeMeasurements(int width, int height)
{
Width = width;
Height = height;
}
public int Width { get; }
public int Height { get; }
}
选项4.修复类MyRectangle
body-它不能使用可变对象:
public class MyRectangle
{
int _height;
int _width;
public MyRectangle(SomeMeasurements arg)
{
_height = arg.Height;
_width = arg.Width;
}
public int GetArea()
{
return _width * _height;
}
}
选项5。进行一些测量
可克隆
并在MyRectangle
构造函数中使用它的Clone()
这些选项中的任何一个都有它的缺陷-可能很难避免重用variable1,
MyRectangle
将其转换为结构可能更复杂,MyRectangle
可以是外部的,您可能根本不会更改它,等等。解决这个问题的最正确方法是什么?通常,您应该传递符合特定接口的服务,或者只在构造函数中传递不可变对象。如果您想保护构造函数不受外部更改的影响,那么构造函数应该获取传递给它的任何可变数据的副本
一旦数据通过构造函数,它就应该被视为新实例状态的一部分,并且不应该在该实例之外进行修改
您的选项3、4似乎最有用。选项2将修复此问题,因为您将数据的副本传递给构造函数。选项1在许多情况下可能不受您的控制。这取决于类之间的关系以及它们的设计用途
如果您考虑从<代码>流>代码>实例构造的<代码> StreamReader <代码>类,则<>代码>流<代码>将继续是“它自己的”可变类,具有自己的职责集,而读者以给定的方式处理它的可变性。这两个对象之间存在持续的关系,如果一个人对
流
做了某件事,那么希望它会影响读者
在这种情况下,我们显然只持有对传递给构造函数的流的引用
在其他情况下,传递一个对象来表示正在创建的对象的初始状态。两者之间没有持续的关系
在这里,最好复制传递的对象或其字段。(对于micro OPT,复制字段会使初始构造稍微慢一点,使用它们也稍微快一点)
你正在处理的情况是你正在设计的一部分,因为你可以决定让一门课以任何一种方式运作。某些情况显然必须是一种情况或另一种情况(在StreamReader
示例中,永远不要保留您正在处理的流
是没有意义的),但通常是有选择的。支持最小惊奇原则,如果您仍然不能决定支持复制方法,即对象之间没有持续的关系,因为您的依赖关系现在更简单了。我想您需要发布GetArea()的代码来回答我根本没有更改我的矩形,我只是将“class”更改为“struct”在某些测量中,请参见
public class SomeMeasurements
{
public SomeMeasurements(int width, int height)
{
Width = width;
Height = height;
}
public int Width { get; }
public int Height { get; }
}
public class MyRectangle
{
int _height;
int _width;
public MyRectangle(SomeMeasurements arg)
{
_height = arg.Height;
_width = arg.Width;
}
public int GetArea()
{
return _width * _height;
}
}