Jelle Druyts .NET Consultant
Just another ignorant weirdo from Antwerp, Belgium trying to make sense out of it all
If you've ever written some test code before (you do write unit tests, don't you?), you probably ran into the common code construct that you initialize a "success" flag to a certain value so you can toggle its state later on. I just wrote a little utility class to guard you from making mistakes here: a boolean-like flag that can only change its state (value) once.
Normally, you would initialize a boolean flag to the expected outcome and then only change that flag if one of the tests failed. You can't set the flag directly everytime because that can reset the value when it should not be reset (e.g. if one test succeeds then the failure of the previous tests would be "forgotten").
Bad code (the result of the first test won't ever matter):
bool success = true; // We expect this to work. success = !HasFirstTestSucceeded(); success = !HasSecondTestSucceeded(); // ... if( success ) Party();
Better code (semantically correct but cumbersome):
bool success = true; // We expect this to work. if( !HasFirstTestSucceeded() ) success = false; // Only change the value if necessary. if( !HasSecondTestSucceeded() ) success = false; // ... if( success ) Party();
So you have to write code that only changes the flag if it differs from its initial state. This is just where the OneShotFlag class helps: it only allows the flag to be changed only once. Furthermore, it can implicitly be converted to a boolean so checking its state is just as easy.
OneShotFlag
But it becomes more natural like this:
OneShotFlag success = new OneShotFlag( true ); // We expect this to work. success.State = HasFirstTestSucceeded(); // Change the value directly. success.State = HasSecondTestSucceeded(); // ... if( success ) Party(); // Note the implicit conversion to a boolean here!
Here's the code for the class:
public class OneShotFlag { /// <summary> /// The current state of the flag. /// </summary> private bool m_State; /// <summary> /// Indicates if the flag has already changed its value once. /// </summary> private bool m_ShotFired; /// <summary> /// Creates a new <see cref="OneShotFlag"/>. /// </summary> /// <param name="initialState">The initial <see cref="State"/> of the flag.</param> public OneShotFlag( bool initialState ) { m_ShotFired = false; m_State = initialState; } /// <summary> /// Gets or sets the current state of the flag. The state will effectively be changed only once. /// </summary> public bool State { get { return m_State; } set { if( m_State != value && !m_ShotFired ) { lock( this ) { m_State = value; m_ShotFired = true; } } } } /// <summary> /// Requests to change the state. The state will effectively be changed only once. /// </summary> public void ToggleState() { State = !State; } /// <summary> /// Implicitly converts the given OneShotFlag to a boolean value. /// </summary> /// <param name="flag">The OneShotFlag to convert.</param> /// <returns>The current <see cref="State"/> of the OneShotFlag.</returns> public static implicit operator bool( OneShotFlag flag ) { return flag.State; } }