2011-12-13 10 views
27

Sto cercando di capire perché string.Empty è readonly e non è un const. Ho visto this Post ma non capisco il commento che Microsoft ha scritto a riguardo. Come Jon Skeet wrote in un commento "Non lo so - non ha molto senso per me, ad essere onesti ..."Significato di commento confuso sopra "string.Empty" in .NET/BCL source?

Shared Source Common Language Infrastructure 2.0 Release. string.cs è in sscli20 \ CLR \ src \ BCL \ system \ string.cs

// The Empty constant holds the empty string value. 
//We need to call the String constructor so that the compiler doesn't mark this as a literal. 
//Marking this as a literal would mean that it doesn't show up as a field which we can access 
//from native. 
public static readonly String Empty = ""; 

non riesco a vedere qui ogni chiamata al costruttore String e, inoltre, è contrassegnato come letterale - ""

Qualcuno può spiegarmi in testo semplice, cosa significa il commento e perché è string.Emptyreadonly e non uno const?


Aggiornamento:
Eric Lippert commentato ormai deleted answer:

ho chiesto a uno dei C# veterani durante il pranzo su questo e lui non ricordava espressamente il motivo per cui questa decisione è stata fatto, ma congetturato che avesse qualcosa a che fare con l'internamento.

+7

Forse è uno di quei commenti che aveva senso a un certo punto, ma poi il codice è stato cambiato e non ha più senso ... non che io abbia mai fatto quello o niente ... * fischia mentre si allontana * –

+41

"Perché non è un const" - perché allora non potresti divertirti a fare 'typeof (string) .GetField (" Empty "). SetValue (null, null);' or 'typeof (string) .GetField ("Empty"). SetValue (null, ""); '- mwahahah; mwaaaahahahahahahhh; MWWWWAAAAAHAHAHAHAHAHH! –

+2

@MarcGravell, dov'è Eric Lippert quando è necessario. "Aiutami Superman ..." – gdoron

risposta

14

La parte importante non è ciò che accade in questa classe, ma cosa succede, quando un altro usi di classe (e link a) esso. Mi spiego con un altro esempio:

Si supponga di avere un Assembly1.dll contenente una classe dichiarando

public static const int SOME_ERROR_CODE=0x10; 
public static readonly int SOME_OTHER_ERROR_CODE=0x20; 

e un'altra classe consumare questo esempio

public int TryFoo() { 
    try {foo();} 
    catch (InvalidParameterException) {return SOME_ERROR_CODE;} 
    catch (Exception) { return SOME_OTHER_ERROR_CODE;} 
    return 0x00; 
} 

Si compila la classe in Assembly2.dll e collegarlo contro Assembly1.dll, come previsto, il metodo restituisce 0x10 su parametri non validi, 0x20 su altri errori, 0x00 in caso di successo.

Soprattutto, se si crea Assembly3.exe contenente qualcosa come

int errorcode=TryFoo(); 
if (errorcode==SOME_ERROR_CODE) bar(); 
else if (errorcode==SOME_OTHER_ERROR_CODE) baz(); 

Essa funzionerà come previsto (Dopo essere stato legato contro Assembly1.dll e Assembly2.dll)

Ora, se si ottiene un nuovo versione di Assembly1.dll, che ha

public const int SOME_ERROR_CODE=0x11; 
public readonly int SOME_OTHER_ERROR_CODE=0x21; 

Se si ricompila Assembly3.exe e collegare l'ultimo frammento contro la nuova Assembly1.dll ed immutato Assembly2.dll, si smetterà di funzionare come previsto:

bar() non sarà chiamato correttamente: Assembly2.dll ricorda letterale 0x20, che non è la stessa 0x21 letterale Assembly3.exe legge di Assembly1.dll

Baz () verrà chiamato correttamente: sia Assembly2.dll che Assembly3.exe fanno riferimento a SYMBOL REFERENCE chiamato SOME_OTHER_ERROR_CODE, che in entrambi i casi è stato risolto dalla versione corrente di Assembly1.dll, quindi in entrambi i casi è 0x21.

In breve: uno const crea un LITERAL, uno readonly crea un SYMBOL REFERENCE.

LITERALS sono interni al framework e non possono essere sottoposti a marshalling e quindi utilizzati dal codice nativo.

Così

public static readonly String Empty = ""; 

crea una symbol reference (resovled al momento del primo utilizzo da una chiamata al cosntuctor String), che può essere schierato un così utilizzato dalla madre, mentre

public static const String Empty = ""; 

sarebbe creare un letterale, che non può.

+1

Quali sono i vantaggi che string.Empty non viene "ricordato" non verrà modificato. const potrebbe andare bene, non è vero? – gdoron

+0

Sospetto che riguardi il marshalling: il commento al codice parla della possibilità di chiamarlo da nativo e i letterali non sono marshallable. –

+0

Mi piacerebbe capire perché i letterali non sono marshallable ... Cosa c'è di diverso tra un letterale e un riferimento che restituisce lo stesso valore? –