Важной частью является не то, что происходит В этом классе, а то, что происходит, когда другой класс использует (и связывает) его. Позвольте мне объяснить еще одним примером:
Предположим, у вас есть Assembly1.dll, содержащая класс, объявляющий
public static const int SOME_ERROR_CODE=0x10;
public static readonly int SOME_OTHER_ERROR_CODE=0x20;
и другой класс, потребляющий это, например.
public int TryFoo() {
try {foo();}
catch (InvalidParameterException) {return SOME_ERROR_CODE;}
catch (Exception) { return SOME_OTHER_ERROR_CODE;}
return 0x00;
}
Вы компилируете свой класс в Assembly2.dll и связываете его с Assembly1.dll, как и ожидалось, ваш метод вернет 0x10 при недопустимых параметрах, 0x20 при других ошибках, 0x00 при успехе.
Особенно, если вы создаете Assembly3.exe, содержащий что-то вроде
int errorcode=TryFoo();
if (errorcode==SOME_ERROR_CODE) bar();
else if (errorcode==SOME_OTHER_ERROR_CODE) baz();
Он будет работать, как ожидалось (после связывания с Assembly1.dll и Assembly2.dll)
Теперь, если вы получите новую версию Assembly1.dll, в которой
public const int SOME_ERROR_CODE=0x11;
public readonly int SOME_OTHER_ERROR_CODE=0x21;
Если вы перекомпилируете Assembly3.exe и свяжете последний фрагмент с новой Assembly1.dll и неизмененной Assembly2.dll, она перестанет работать должным образом:
bar () не будет вызываться правильно: Assembly2.dll запоминает ЛИТЕРАЛЬНЫЙ 0x20, который не является тем же литералом 0x21, который Assembly3.exe считывает из Assembly1.dll.
baz () будет вызываться правильно: как Assembly2.dll, так и Assembly3.exe ссылаются на СИМВОЛ REFERENCE, называемый SOME_OTHER_ERROR_CODE, который в обоих случаях разрешается текущей версией Assembly1.dll, таким образом, в обоих случаях это 0x21.
Вкратце: const
создает LITERAL
, readonly
создает SYMBOL REFERENCE
.
LITERALS
являются внутренними по отношению к фреймворку и не могут быть упорядочены и, следовательно, использоваться в машинном коде.
So
public static readonly String Empty = "";
создает symbol reference
(восстанавливается во время первого использования вызовом String cosntuctor), который может быть упорядочен и таким образом использован из нативного, в то время как
public static const String Empty = "";
создаст литерал, который не может.
person
Eugen Rieck
schedule
18.12.2011
typeof(string).GetField("Empty").SetValue(null, null);
илиtypeof(string).GetField("Empty").SetValue(null, " ");
- mwahahah; мваааахахахахахаххх; MWWWWAAAAAHAHAHAHAHAHH! - person Marc Gravell   schedule 13.12.2011