2013-04-12 5 views
11

Perché i seguenti lavori?Inizializzazione array multidimensionale Const

class A 
{ 
    public int[,] i = { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } }; 

    static void Main(string[] args) 
    { 
    } 
} 

considerando che quanto segue non?

class A 
{ 
    public const int[,] i = { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } }; 

    static void Main(string[] args) 
    { 
    } 
} 

Non consente un tipo di riferimento const diverso da stringa per essere assegnato diverso da null. Poiché si tratta di un array (riferimento), deve essere assegnato null (?). Come sarebbe inizializzato se è costante e nullo?

risposta

14

Fa parte del linguaggio design di C#, se non ricordo male. const è riservato agli elementi che possono dedurre il loro contenuto in fase di compilazione, vale a dire prima (durante) il programma viene persino creato e quindi eseguito. Tutti gli array in C# sono array di runtime (le loro lunghezze sono determinate quando il programma è in esecuzione, non prima di allora) e quindi non possono essere trasformati nei campi const. Sento che è un limite di C#, ma è così che hanno deciso di farlo.

Il motivo di riferimento può essere nullo è che null è un valore costante, mentre l'inizializzatore (che viene eseguito in fase di esecuzione) non lo è. null è incorporato nel linguaggio, quindi con quella logica il suo valore è sempre noto, sempre (e quindi utilizzabile per i tipi di riferimento in fase di compilazione).

EDIT:

Si dovrebbe essere in grado di fare una tabella statica, però, che verrà inizializzato il momento in cui viene utilizzato o necessario per qualsiasi altro codice:

public static int[,] i = { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } }; 
    ^Static Keyword 

è possibile accedervi come (se è ancora in class A):

A.i[0, 1] 

Spero che ti aiuta

Per saperne di più, guarda MSDN: http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(CS0134);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5)&rd=true

EDITEDIT: Se è necessario rivetto la tabella statica per il codice e non permettere a nessuno di cambiarla dopo che è stato inizializzato, c'è la parola chiave readonly a tal fine:

Ricorda che non ti impedirà di riassegnare le cose in quegli slot, ma è fisso quanto C# può darti, salvo fare una proprietà o restituire un nuovo array ogni volta.

+0

Tutto quello che posso dire è wow. Mi sta costringendo a trovare modi per creare tabelle di numeri interi costanti, oltre al più ovvio. – user2255673

+0

@ user2255673 Se stai cercando qualcosa come 'const * const' di C++, non lo troverai in C#. –

+0

@ user2255673 Sì, è piuttosto sfortunato. Ma puoi creare tabelle statiche di numeri interi e operare su quelli, ho modificato la mia risposta per mostrarti. –

3

Non funziona perché questa è la restrizione sulla parola chiave const.

Da MSDN:

La parola chiave const viene utilizzato per modificare la dichiarazione di un campo o variabile locale . Specifica che il valore del campo o la variabile locale è costante, il che significa che non può essere modificato.

Un'espressione costante è un'espressione che può essere completamente valutata in fase di compilazione.Pertanto, gli unici valori possibili per le costanti di tipi di riferimento sono stringa e nulla

Se si sta tentando di definire una matrice che non può cambiare, forse si dovrebbe utilizzare la parola chiave readonly, che limitano le modifiche di essere reso a un campo o variabile locale a una dichiarazione o nel costruttore.

+2

Nota che readonly renderà l'array _reference_ solo in lettura. I contenuti sono ancora mutabili per indice per chiunque abbia un riferimento alla matrice. –

+0

@DanBryan: Effettivamente –

2

Le costanti vengono valutate in fase di compilazione. Gli array sono tipi di riferimento e l'unico modo per creare un tipo di riferimento è utilizzare la parola chiave new (che è implicita nel codice).

new non può essere utilizzato in un'espressione costante, perché non può essere valutato in fase di compilazione.

Vedi MSDN: http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(CS0134);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5)&rd=true

+1

Nota che le stringhe sono un po 'un avvertimento, poiché le stringhe sono tipi di riferimento, ma hanno uno speciale supporto per caricarle come costanti dal codice IL sottostante. –

+0

Infatti, probabilmente avrei dovuto dirlo. –