I’m doing a big refactor of a pile of code that used to use a bunch of multidimensional arrays that were constantly getting resized. I created a data object to replace the 2D array, and I’m now passing a list of these around.
I discovered something that worries me a little though. Let’s say I have some code that looks like this:
List<NCPoint> basePoints = new List<NCPoint>();
// ... snip populating basePoints with starting data
List<NCPoint> newPoints = TransformPoints(basePoints, 1, 2, 3);
public List<NCPoint> TransformPoints(List<NCPoint> points, int foo, int bar, int baz){
foreach(NCPoint p in points){
points.X += foo
points.Y += bar
points.Z += baz
}
return points;
}
The idea is to keep a list of the original points (basePoints) and a list of the updated points (newPoints). But C# passes the list by reference, as with any object. This updates basePoints in place, so now both basePoints and newPoints will have the same data.
At the moment, I’m trying to be careful about making a full copy of the passed-in List before I muck with the data. Is that the only sensible way to make sure changes to an object within a function don’t have side effects outside the function? Is there anything akin to passing an object with const?
In short: no.
C# does not have the concept of a
constreference, per se. If you want to make an object immutable, you must code it explicitly so or take advantage of other “tricks”.You can make your collection immutable in many ways (
ReadOnlyColelction, return an iterator, return a shallow copy) but that only protects the sequence, not the data stored inside.Thus, what you’d really need to do what you want is to return a deep copy or projection, possibly using LINQ:
Also, the beauty of returning an iterator (as opposed to just returning a
List<T>as anIEnumerable<T>, etc.) is that it can’t be cast back to the original collection type.UPDATE: Or, in .NET 2.0 parlance:
The point is, there are many ways to treat something as immutable, but I wouldn’t try to implement C++-style “const correctness” in C# or you will go mad. Implement it as needed when you want to avoid side-effects, etc.