如何确保自己不会错误地更新当前对象上的另一个对象?
您能否建议我一种方法,在我使用引用类型时防止出现这种情况?
var someCost = new Cost( Price: new Price(1000, "USD")
, CostType: "Type-A") ;
var candyCost = new Cost();
// Initialize candyCost.Price
candyCost.Price = someCost.Price; //Now candyCost Price is referencing
// price of someCost;
// (.......)
// Some logic and code here
//and I forgot that I was referencing to someCost object's price object
//and I do stupid mistake:
candyCost.Price.Value = 5000; //Now I believe I have updated candyCost price
//but I have also updated someCost!!
故事的其余部分是关于调试以找出为什么 someCost 的价格会更新。
我想用这个例子来简化问题。我希望你能明白我的意思。
问题:您能给我推荐一种方法来确保自己不再犯这样的错误吗?涉及更新引用类型上的值时的任何设计模式。
Can you suggest me a way that would prevent me from such a case when I am working with reference types?
var someCost = new Cost( Price: new Price(1000, "USD")
, CostType: "Type-A") ;
var candyCost = new Cost();
// Initialize candyCost.Price
candyCost.Price = someCost.Price; //Now candyCost Price is referencing
// price of someCost;
// (.......)
// Some logic and code here
//and I forgot that I was referencing to someCost object's price object
//and I do stupid mistake:
candyCost.Price.Value = 5000; //Now I believe I have updated candyCost price
//but I have also updated someCost!!
Rest of the story is about debugging to find out why someCost's Price is updated.
I wanted to simplify the problem with this example. I hope if you get my meaning.
Question: Can you recommend me a way to secure myself from repeating such a mistake? any design patterns when it comes to updating values that are on reference types.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
您的
Price
对象应该是不可变的 - 这将迫使您分配一个新的Price
对象,而不是更改现有对象的价格,从而避免副作用。Your
Price
object should be immutable - this will force you to assign a newPrice
object instead of changing the price of an existing one, hence avoiding the side effect.取决于您想通过这一行实现什么:
您是否想说
candyCost
和someCost
此时 具有相同的价格,或者他们总是有相同的价格?如果您只想使用等于
someCost.Prize
的值来初始化candyCost.Price
,那么您应该克隆Price
实例:(当然你必须实现构造函数)
Depends on what you want to achieve with this line:
Do you want to say, that
candyCost
andsomeCost
have the same price at this moment or that they always have the same price?If you just want to initialize
candyCost.Price
with a value that is equal tosomeCost.Prize
, than you should clone thePrice
instance:(of course you have to implement the constructor)
从不创建两个表示相同事物的局部变量。
By never creating two local variables that represent the same thing.
通过实现 IClonnable 接口创建 Price 类的深层副本。然后,当您分配价格时,您会说
或者
这样您将永远不会忘记
,因此您无法直接访问 _price 字段,除非您调用 Getter 属性,该属性最终将返回价格的深层副本
Create a deep copy of the class Price by implementing the IClonnable interface. Then when you assign the price you would say
or
this way you will never forget
hence you cannot access _price field directly, unless you call the Getter property which will eventually return a deep copy of the Price
在这种情况下,我建议使用
struct
(值类型)而不是class
(引用类型)。这样就不可能引用同一个实例,因为没有“引用”,值本身被存储:)您还可以将
Price
类型的属性设置为只读,并且仅设置由构造函数。这样您就可以引用另一个副本,但这没有问题 - 它们都将保持相同的值,因为要设置为新值,您需要创建一个新对象。In this case I'd suggest using a
struct
(value-type) instead of aclass
(reference type). That way it's not possible to refer to the same instance, because there's no 'reference', the value itself is stored :)You could also have the properties of the
Price
type read-only, and set only by the constructor. That way you can reference another copy, but that's no problem - they'll both stay at the same value because to set to a new value you'd need to create a new object.您希望 Price 属性具有按值行为。 getter 应该返回 Price 对象的副本。
You want a by-value behaviour for the Price property. The getter should return a copy of the Price object.
有几种方法可以做到这一点。
不可变性乍一看似乎是一种非常痛苦的限制性方法,但实际上它很常见,并且很好地强制执行了您想要做的事情。
使用复制构造函数意味着您必须确保每当您返回一个对象(例如,从 getter)时,您实际上都会创建一个新对象,同样,每当您使用传入的对象(例如,setter)时,您都需要复制它。
There are a couple of ways of doing it.
Immutability might seem like quite a painfully restrictive method at first but actually it's quite common and enforces what you are trying to do quite well.
Using copy constructors means you have to make sure that whenever you return an object (e.g. from a getter) you actually create a new object, similarly whenever you use a passed in object (e.g. setter) you need to copy it.
使用 {get; 将 Cost.Price 设为只读私人套装;}
向 Cost 添加一个名为 SetPrice 的新方法,该方法接受 Price 并创建一个新的 Price 实例
您需要使 Price 实现 IClonnable
Make Cost.Price read-only using {get; private set;}
Add an new method to Cost called SetPrice which takes a Price and creates a new Price instance
You will need to make Price implement IClonnable
根据语言的不同,您可以进行运算符重载。因此,重载赋值运算符 (
=
) 并在重载的运算符主体中执行深度克隆。Depending on the language, you can do operator overloading. So, overload the assignment operator (
=
) and perform a deep clone in the overloaded operator body.