Yesterday, I introduced the ICommunicationObject state machine and mentioned that we had a base class called CommunicationObject to take care of some of the state machine details for you. Today, I'll show off one of the ways that CommunicationObject deals with state.
When you're writing a channel, many of the operations that you'll be implementing are only safe to call when the channel is in a particular state. As I said before, once a channel has been opened, you can't change any of its configuration settings. It's a really bad idea to try to read or write from a channel after it's been closed. It isn't much better to try to read or write from a channel before it's been opened.
You can invent your own reasons for why an operation should only work when in certain states. CommunicationObject helps you enforce these state requirements with three methods.
protected void ThrowIfDisposed();
protected void ThrowIfDisposedOrImmutable();
protected void ThrowIfDisposedOrNotOpen();
These methods are almost self-documenting although there are a few quirks. The first quirk is that all of the methods will throw if the state is Faulted, even though being faulted is not quite the same thing as being disposed. This is probably what you wanted though because very few channel operations should continue to work after a fault.
Here's how the methods decide whether to throw:
And, here's how the methods decide what to throw:
Next time: Lifecycle of a Channel