The simplest solution is to merge Initialize with the constructor. That way, the object will never be available for the client in the the uninitialized state so the error is not possible. In case you cannot do the initialization in the constructor itself, you can create a factory method. For example, if your class requires certain events to be registered, you could require the event listener as a parameter in the constructor or factory method signature.
Compared to runtime exceptions, it is more work to represent states as distinct classes, but it also givegives you compile-time guarantees that you are not calling methods which are invalid for the object state, and it documents the state transitions more clearly in code.
If you have complex temporal coupling (a number of methods must be called in a certain order), one solution could be to use inversion of control, so you create a class which calls the methods in the appropriate order, but uses template methods or events to allow the client to perform custom operations at appropriate stages in the flow. That way, the responsibility for performing operations in the right order is pushed from the client to the class itself.
A simple example: You have a File-object which allows you to read from a file. However, the client needs to call Open before the ReadLine method can be called, and needneeds to remember to always call Close (even if an exception occurs) after which the ReadLine method must not be called anymore. This is temporal coupling. It can be avoided by having a single method which takes a callback or delegate as an argument. The method manages opening the file, calling the callback and then closing the file. It can pass a distinct interface with a Read method to the callback. That way, it is not possible for the the client to forget to call methods in the correct order.