Earlier today, I got a question through Twitter in response to my recently published video: Clean Code: The Refactoring Bits. Since I can't answer adequately in 140 characters, I thought it would be better to answer here.
What is the best way to refactor C# code containing goto statements?
This is my standard answer to pretty much everything. It's nearly impossible to answer a question like this without further context. I tend to stay away from the words "always" and "never" just because they tend to over-simplify things. And the real world is never simple.
As an example, I have heard of developers who say that say we should never use a "switch" statement; instead, we should use the Strategy Method pattern. A dramatic over-simplification.
I'll say the same thing here. The "goto" statement has fallen out of favor over the years. The primary reason is that it tends to make code more difficult to follow. And in the circles I've been in, the developers don't even know the C# syntax off the top of their heads. But just because you run across a "goto" doesn't mean it must be changed. Again, it depends.
I'm definitely not a refactoring expert, but I will point to some resources.
The first is Working Effectively with Legacy Code by Michael C. Feathers (Jeremy's review). The thing that I really like about this book is the emphasis on unit testing. Before doing any refactoring, we need to bring the current code under effective automated testing. This way, when we start our refactoring, we get nearly immediate feedback if we inadvertently break something.
This is something that I show several times in the refactoring video. If our refactoring goes awry, our unit tests let us know about it right away so that we can take action.
There are two other books that are generally recommended: Refactoring: Improving the Design of Existing Code by Martin Fowler and Refactoring to Patterns by Joshua Kerievsky. Both of these books are currently in my library, but they are still in the "To Be Read" pile. I've flipped through both of them and see lots of useful advice, but I haven't actually sat down to read them yet.
These resources will help get us headed in the right direction. But, ultimately, like every other situation that we deal with in programming, what we actually should do depends on the particular situation.