Tutto nella mia risposta è solo il mio pensiero su "perché sarebbe pericoloso consentire questo tipo di accesso". Non so se questo è il vero motivo per cui è stato limitato.
C# spec dice, che l'inizializzazione di campo avviene nei campi di ordine sono dichiarati nella classe:
10.5.5.2. Instance field initialization
The variable initializers are executed in the textual order in which they appear in the class declaration.
Ora, diciamo che il codice che hai citato è possibile - è possibile chiamare metodo di istanza da campo inizializzazione. Potrebbe rendere possibile il seguente codice:
public class Progressor
{
private string _first = "something";
private string _second = GetMyString();
private string GetMyString()
{
return "this is really important string";
}
}
Fin qui tutto bene. Ma cerchiamo di abusare di questo potere un po ':
public class Progressor
{
private string _first = "something";
private string _second = GetMyString();
private string _third = "hey!";
private string GetMyString()
{
_third = "not hey!";
return "this is really important string";
}
}
Quindi, _second
di ottenere inizializzato prima _third
. GetMyString
corre, _third
get "non è hey!" valore assegnato, ma in seguito viene eseguito l'inizializzazione del proprio campo ed è impostato su "hey!". Non molto utile né leggibile, giusto?
Si potrebbe anche usare _third
entro GetMyString
metodo:
public class Progressor
{
private string _first = "something";
private string _second = GetMyString();
private string _third = "hey!";
private string GetMyString()
{
return _third.Substring(0, 1);
}
}
Che cosa vi aspettate di essere valore _second
? Bene, prima che l'inizializzazione del campo esegua tutti i campi ottengono valori predefiniti. Per string
sarebbe null
, quindi riceverai inaspettato NullReferenceException
.
Quindi, imo, i progettisti hanno deciso che è solo più facile impedire alle persone di fare questo tipo di errori.
Si potrebbe dire, OK, non consentire l'accesso alle proprietà e ai metodi di chiamata, ma consenti l'utilizzo di campi dichiarati sopra quello da cui si desidera accedervi. Qualcosa di simile:
public class Progressor
{
private string _first = "something";
private string _second = _first.ToUpperInvariant();
}
ma non
public class Progressor
{
private string _first = "something";
private string _second = _third.ToUpperInvariant();
private string _third = "another";
}
Questo è sembra utile e sicuro. Ma c'è ancora un modo per abusarne!
public class Progressor
{
private Lazy<string> _first = new Lazy<string>(GetMyString);
private string _second = _first.Value;
private string GetMyString()
{
// pick one from above examples
}
}
E tutti i problemi con i metodi capita di tornare di nuovo.
L'unica cosa che mi viene in mente è il fatto, che quando l'inizializzazione di un campo particolare esegue tutti gli altri campi possono o non possono ancora essere inizializzati. L'esecuzione di un metodo di istanza in quel punto, che consentirebbe l'accesso a tutti i membri dell'istanza, consente di accedere ad altri campi che non erano ancora inizializzati. Questa è una potenziale fonte di problemi. Perché è consentito nel costruttore? Poiché tutti i campi vengono inizializzati prima dell'esecuzione del codice del costruttore. – MarcinJuraszek
@MarcinJuraszek Questa è stata la mia comprensione, anche se è possibile rendere l'argomento che il runtime potrebbe semplicemente inizializzare tutti i campi sui valori predefiniti (ad esempio 0, null, ecc.), Quindi eseguire le inizializzazioni del campo, quindi eseguire il costruttore applicabile. – sdzivanovich
@sdzivanovich Questo è esattamente ciò che accade: tutti i campi vengono inizializzati con valori predefiniti prima che avvenga l'inizializzazione.Ma ancora non risolve il problema del codice di inizializzazione essendo imprevedibile (vedi la mia risposta). – MarcinJuraszek