Предыдущие ответы были правильными для .NET 1.1 (посмотрите дату поста, на который они ссылались: 2003). Начиная с .NET 2.0 и более поздних версий, по сути, нет никакой разницы. JIT все равно будет ссылаться на один и тот же объект в куче.
В соответствии со спецификацией C #, раздел 2.4.4.5:
http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx
Каждый строковый литерал не обязательно приводит к новому экземпляру строки. Когда два или более строковых литерала, эквивалентных по оператору равенства строк (раздел 7.9.7), появляются в одной сборке, эти строковые литералы ссылаются на один и тот же экземпляр строки.
Кто-то даже упоминает об этом в комментариях к посту Брэда Абрама
Таким образом, практический результат "" против String.Empty равен нулю. JIT выяснит это в конце.
Лично я обнаружил, что JIT намного умнее меня, и поэтому я стараюсь не слишком умничать с такими оптимизациями микрокомпилятора. JIT развернется для циклов (), удалит избыточный код, встроенные методы и т. Д. Лучше и в более подходящее время, чем когда-либо мог ожидать компилятор I или C #. Пусть JIT сделает свое дело:)