We're cracking down on static variables in Schizoid so we can feel more comfortable that there aren't lurking thead safety issues in there. Some of these statics are effectively constants, but we made them non-constant to ease unit testing. For example, we might set a unit cap at 1 in a test, create two units, and make sure the cap is being respected.
Unfortunately, now there's no way to make sure that an Evil Programmer doesn't violate the effective const-ness of this variable...and possibly endanger our thread safety.
(In case you're about to say "Why not make it private and add Get/Set accessors", shame on you for parrotting rote "good style" guidelines that don't actually do anything to protect you. One could then use the Set and violate our thread safety that way.) In a better world, C# would have friends. We could make the test fixture a friend of the class with the static variable and walk away happy.
You can have friend DLL's - I could just see myself breaking my project down into dozens of small DLL's just to get the kind of granularity of friendliness that I want. A lot of DLL's seems to hurt our build time, however.
I came across a possible answer in *CLR via C#* today - "Note that reflection can be used to modify a readonly field," Richter says.
That's good enough, I thought. I'll make my consts readonly, use reflection to modify them in the test program, and assume that no programmer will be So Evil that they do the same thing in the core code. Too much work! The forces of Evil, after all, are lazy.
Unfortunately, it didn't work. Maybe a C# guru in the audience can tell me why.
Here's the code. Enemy is the class which has the static readonly field maxEnemies.
Type enemyType = typeof(Enemy);
FieldInfo maxEnemiesField = enemyType.GetField("maxEnemies");
When I step through this code in the debugger, Enemy.maxEnemies appears to correctly change to newMax after executing line 3. But then the assertion on line 4 fires, telling me that it's still 100.
WTF? The debugger sees one thing, the code another?
No doubt this is a subtle intracacy of the CLR that somebody out there understands? Googling turned up a lot of noise for me, unfortunately.
BTW - this is all just academic. We don't have any Evil Programmers, really. We don't normally waste a lot of time to protect ourselves from bugs that nobody on the team is actually going to write. But now I'm curious, damn it.