2011-12-30 8 views
12

Sto imparando C# e sto cercando di capire gli aspetti "orientati al tipo" di esso.casting system.array object to int [] string o altri oggetti del tipo

Quindi l'altro giorno ho avuto bisogno di ricevere un oggetto System.Array da un metodo. Poi ho provato a lavorare con i singoli oggetti, quindi ho provato ad indirizzarlo con un indice. Il compilatore non mi ha permesso di dire che l'oggetto System.Array non supporta l'indicizzazione.

Ma non è Array la classe base di tutti gli array (System.Array on msdn)? In che modo int [] supporta l'indicizzazione e l'array [] no?

Ecco il codice per dimostrare il problema:

int[] intArray = {1,2,3,4,5,6,7,8,9,10}; 
int t; 
Array sysArray;  
Console.WriteLine("{0}", intArray.GetType().ToString()); // output: System.Int32[] 
sysArray = Array.CreateInstance(typeof(int), 10); 
Console.WriteLine("{0}", sysArray.GetType().ToString()); // output: System.Int32[] 
sysArray = intArray; //compiles ok 
//t = sysArray[4]; This line produces error Error 2 Cannot apply indexing with [] to an 
// expression of type 'System.Array' 
//t = intArray[4]; This line compiles ok 

Quindi quello che abbiamo qui è 2 oggetti, che sembrano essere dello stesso tipo. Ma uno sta implementando l'indicizzazione e l'altro no, come è possibile?


un riferimento alle risposte

dopo aver letto i tuoi commenti Penso che ho avuto il senso delle cose. int [] è e matrice di oggetti. ognuno degli oggetti è una struttura di tipo int32. La matrice [] è una matrice di oggetti. ognuno degli oggetti è una classe di tipo Array. significato: una matrice di matrici. come posso visualizzare nel codice seguente:

Array[] sysArrayOfArray = new Array[SIZE_OF_THE_MOTHER_ARRAY]; 
sysArrayOfArray[0] = Array.CreateInstance(typeof(int),SIZE_OF_FIRST_CHILD_ARRAY); 
sysArrayOfArray[1] = Array.CreateInstance(typeof(int),SIZE_OF_FIRST_SECOND_ARRAY); 

e così via ... così ho capito perché il modo in cui ho cercato di accedere agli elementi di sysArray era sbagliato. intArray -> 1 array di molti int sysArray -> 1 classe (che consente l'accesso a molti interi)

dal punto di vista sysArray della lingua non è una matrice a tutti, è solo un riferimento 1 oggetto (di tipo System.Array)

(mi dispiace per ripetere un po ', ma aiuta davvero le cose insieme nella mia testa)

grazie a tutti per guidare nella comprensione di tale differenza.

per quanto riguarda le soluzioni .. che quello che cercavo e ha lavorato per me migliore:

Array sysArray = Array.CreateInstance(typeof(int),3); 
int[] intArray = new int[3]; 
int one, ten, hundred; 
sysArray.SetValue(1, 0); 
sysArray.SetValue(10,1); 
sysArray.SetValue(100,2); 
intArray = (int[])sysArray;// works, but forces me to create a new reference 
one = ((int[])sysArray)[0];// works and is exactly what i was looking for... 
ten = ((int[])sysArray)[1]; 
hundred = ((int[])sysArray)[2];  
+0

La tua domanda non è chiara. Un int è un oggetto .... Quindi quello che stai facendo ha poco senso. –

risposta

11

Casting si prenderà cura della differenza:

t = (sysArray as int[])[4]; 

Stai visualizzando che entrambe le matrici sono di tipo System.Int32[], perché sono (che è il motivo per cui questo cast funziona).

5

int viene dichiarata come struct nella BCL

public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<Int32>, Equatable<Int32> 

Mentre Array è dichiarato in questo modo :

public abstract class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable 

Quindi non sono realmente uguali.

Se si vuole ottenere elementi dal Array utilizzando un indicizzatore, penso che sarà necessario fare questo:

int number = ((IList<int>)sysArray)[4]; 

Il motivo è dovuto al modo in cui il metodo di indicizzatore viene dichiarato in Array:

Object IList.this[int index] { 
    get { return GetValue(index); } 
    set { SetValue(value, index); } 
} 

Poiché IList è dichiarato nella firma, significa che è necessario trasmettere sysArray in un IList<int> per accedere all'indicizzatore. Se, invece, l'indicizzatore era stato dichiarato come questo:

Object this[int index] { 

allora sì, si potrebbe fare sysArray[0]; senza problemi.

+0

Ancora, l'OP non sta chiedendo perché un singolo 'int' non può essere indicizzato. Chiedono perché un oggetto generico 'System.Array' non può essere indicizzato. –

+0

Quando si utilizza 'int []' si sta effettivamente utilizzando un costrutto del linguaggio C#, cioè gli array. Ciò significa che esiste un supporto integrato per l'accesso all'indice, ad es. 'Myarray [23];'. In sostanza, l'accesso a un array di 'structs' (int) La classe' Array' è un oggetto in sé, e quindi quando si usa l'accesso all'indice su di esso, non si sta usando il linguaggio C#, piuttosto si sta usando qualunque sia il il metodo indexer è su quella classe cioè 'Object IList.this [int index]'. Quindi, in poche parole, i metodi di accesso all'indice per ogni tipo sono totalmente diversi. –

+0

Non penso che gli array siano un "costrutto del linguaggio C#". L'utilizzo di parentesi quadre per l'indicizzazione degli elementi dell'array è un costrutto linguistico ... l'esistenza di matrici è una caratteristica fondamentale della CLI. Vedi ** ECMA-335: 8.9.1 Tipi di array **. Per quanto riguarda IList, include (come si nota) l'indicizzatore 'this [int index]'. Quindi, come System.Array può implementare IList senza implementare il membro richiesto 'this [int index]'? –

1

È necessario esaminare le interfacce implementate da ciascun oggetto. Array implementa System.Collections.IList che fornisce un indicizzatore di oggetti mentre int non fornisce un'implementazione IList.

+1

Questo non è ciò che l'OP sta insinuando. L'OP sta chiedendo perché la classe astratta System.Array non consente l'accesso agli elementi usando la sintassi dell'indicizzatore: è l'espressione 'sysarray [4]' che bombarda. –

1

System.Array è una classe di base astratta. La documentazione microsoft dice tutto ...

Provides methods for creating, manipulating, searching, and sorting arrays, thereby 
serving as the base class for all arrays in the common language runtime. 

System.Array non fornisce un'implementazione per l'indicizzatore.

che cosa funziona per voi è questo ...

int[] sysArray = (int[])Array.CreateInstance(typeof(int), 10); 
1

Supponendo eventTypes sono oggetti che contengono valori interi (object[] eventTypes):

int[] eventTypeIDs = eventTypes.Select(Convert.ToInt32).ToArray(); 
0

È possibile leggere i valori di matrice utilizzando la funzione GetValue.

array.GetValue(1); 
array.GetValue(1,2);