One of the many wonderful innovations in C# 2.0 was the introduction of support for Edit-and-Continue. I'm finding it incredibly useful when refactoring legacy code particularly for an operation made up of many sub-steps.
While testing the refactored version of the operation by stepping through it in the debugger I'll encounter a section of code that's missing some logic or is putting data in the wrong place.
Before C# 2.0 this situation meant Detach, Terminate, re-compile, restart, re-attach (for Windows Services at least), then resume.
With C# 2.0 and beyond you can edit the code while stepping through it in the debugger. The IL is dynamically updated (or if it has already been JITed, native instructions are updated).
This is a huge time savings. Given a sufficiently convoluted execution environment the Detach, Terminate, Recompile, Restart, Re-attach and Resume cycle can take several minutes. With Edit-and-Continue I get to skip it entirely until encountering a need to perform an operation that can't be done during Edit-and-Continue (e.g., adding a method).