Consider this C# program:
using System;
using System.Collections.Generic;
using System.Linq;
namespace SandboxApplication
{
public class IntsOwner
{
private List<int> _ints;
public IntsOwner (IEnumerable<int> ints)
{
_ints = ints.OrderBy(i => i).ToList(); // They must be in the correct order
}
public IEnumerable<int> Ints
=> _ints;
public void CheckFirstTwoInts ()
{
if (_ints.Count < 2)
{
Console.WriteLine("You need to collect some more ints before trying this.");
}
else if (_ints[0] <= _ints[1])
{
Console.WriteLine("Your ints are in the correct order and you should stop worrying.");
}
else
{
Console.WriteLine("You've failed, your highness.");
}
}
}
class Program
{
static void Main (string[] args)
{
var intsOwner = new IntsOwner(new List<int> {1, 2, 3, 4, 5});
var ienumerable = intsOwner.Ints;
var list = (List<int>)ienumerable;
intsOwner.CheckFirstTwoInts();
list[0] = 6;
intsOwner.CheckFirstTwoInts();
Console.ReadLine();
}
}
}
If you run this, you will get two lines of output:
Your ints are in the correct order and you should stop worrying.
You've failed, your highness.
The original designer of the IntsOwner
class wanted to make sure that a particular property (ordering of list elements) held for the private member _ints
. But because a reference to the actual object is returned through the Ints
property, a user of the class can modify the object so that this property no longer holds.
This sort of code doesn't appear very likely in practice, but it is still disconcerting that control of members intended to be private can "leak" in this way. How much, if at all, should programmers try to block this sort of thing off? For example, would it be reasonable or proportionate to change the Ints
property's expression body to _ints.Select(i = i)
and thereby close off this way of modifying the private member? Or would that be unnecessarily paranoid to the detriment of the code's readability?