Ok, but when would you ever want that behaviour? An issue at work recently provided an example: when you can't trust that the thing your object was passed won't be changed. Or that the object you passed in turns out to be the same one passed out later. Here's an example:
There is a class, PersonUsingClasses, that takes items from two data sources and holds on to the references, rather than making copies of all of the properties of each. It then uses those references to construct a new property, DisplayName. I've written such code myself, unaware of the dangers. This class also has a way to convert it back to one of the data source types, ToServicePerson.
A couple of things to notice:
- The PersonClassFromService reference sent into the constructor is the same one passed out in ToServicePerson
- Someone forgot to remove his debugging code in the constructor.
One option to fix this is to not hold on to the references passed into the constructor and make copies of every property that matters to PersonClassUsingClasses. That might be a good option, but we need to support recreating the PersonClassFromService object, which could have properties that don't matter. Or, there could be dozens and dozens of properties to track. (I worked at a bank - trust me when I say this happens.)
A nearly equivalent approach is to use return structs from the DB and service:
Now the system copies every property in every input parameter for us because they are structs. It copies every property again when we call ToServicePerson. This means that changing the input parameter does not get reflected in PersonUsingStructs and we can detect the accidental change in the constructor. This approach uses more memory because of all of this copying, but it's not much more than if we'd made copies of every property ourselves in PersonUsingClasses. We've protected the system from accidental changes.
No comments:
Post a Comment