7
votes

C # - Erreur du compilateur - Lors de l'attribution d'int [] à l'objet []

    List<object> objectList = new List<object>();
    List<string> stringList = new List<string>();
    objectList = stringList;

1 commentaires

Comprenez-vous les différences entre type de valeur et types de référence?


5 Réponses :


6
votes

uniquement des tableaux de types de référence (comme String ) peut être assigné aux tableaux d'autres types de référence (comme objet ). Étant donné que int est un type de valeur, les tableaux ne peuvent pas être attribués à des tableaux d'autres types.

Pour être plus précis, cela s'appelle Array Covariance . Cela ne fonctionne que lorsque les modèles de bits stockés dans la matrice sont compatibles avec le type de destination. Par exemple, les bits dans une chaîne [] sont toutes des références aux chaînes et peuvent être copiées en toute sécurité dans des emplacements de mémoire stockant des références aux objets. Toutefois, une gamme de types de valeur stocke les données réelles des éléments (par opposition aux juste références à eux). Cela signifie qu'un int [] stocke les entiers réels 32 bits dans les éléments de la matrice. Étant donné qu'un entier 32 bits ne peut pas être copié en toute sécurité dans un emplacement de mémoire stockant une référence à un objet ou à un autre type, vous ne pouvez pas attribuer de tableau d'entre eux à un tableau d'un autre type.

Notez que techniquement les bits d'un int peuvent être copiés en toute sécurité dans un emplacement de mémoire stockant un uint (et inversement). Cela signifie que vous devriez être capable de faire quelque chose comme int [] x = nouveau uint [10] . Ce n'est pas réellement de covariance et c # ne le permet pas. Cependant, il est légal dans le CLR et vous pouvez convaincre C # de vous laisser le faire si vous le souhaitez.


2 commentaires

Mais tout est finalement système.Object


Merci gabe. Array Covariance est la clé!



1
votes

Ce que je vois, c'est qu'un tableau de types de référence peut être attribué d'un autre tableau de types de référence lorsqu'un tableau de types de valeur ne peut pas. A du sens pour moi


0 commentaires

2
votes

chaîne et objet sont les deux types de référence. C'est-à-dire qu'une variable de ces types stocke réellement un pointeur à ailleurs en mémoire. int est un type de valeur. C'est-à-dire que les données sont stockées directement lorsque la variable est déclarée.

Cela signifie qu'un tableau de types de référence est fondamentalement différent de celui d'une gamme de types de valeur. Un tableau de types de référence est stocké comme une éventail de pointeurs. Parce que les pointeurs sont de la même taille, cela signifie que pour ré-interpréter une chaîne [] sous forme d'objet [] SIMPY signifie régler la vérification de type effectuée lors de l'accès des éléments le tableau (à peu près).

Cependant, dans un int [] , les valeurs sont stockées directement dans la matrice; Les valeurs INT sont concaténées ensemble. Aucun pointeurs n'est impliqué. Cela signifie que pour ré-interpréter un int [] sous forme d'objet [] nécessite une boxe chaque valeur stockée dans le tableau dans un objet. Par conséquent, pourquoi vous ne pouvez pas le faire en utilisant une simple distribution ou une mission - c'est une opération O (n) qui crée un nouveau tableau. Au lieu de cela, vous pouvez utiliser array.copy qui traite de toute la boxe pour vous.


0 commentaires

0
votes

Si vous avez une installation Visual Studio, vous trouverez la précision de la langue C # en tant que fichier DOC quelque part sous VC #. Le chapitre 12.5 traite de la covariance et il dit

pour deux types de référence A et B, si une référence implicite La conversion (§6.1.6) ou une conversion de référence explicite (§6.2.4) existe de A à B, la même conversion de référence existe également de la Array Tapez A [R] sur le tableau de type B [R], où R est donné Spécificateur de rang (mais identique pour les deux types de matrices). Cette relation est connu sous le nom de Covariance de la matrice.

Cela peut ne pas répondre à votre question, mais c'était une décision délibérée dans la spécification de le faire de cette façon.


0 commentaires

2
votes

Pourquoi cela ne fonctionne pas dans de nombreuses réponses ici, je ne vais donc pas essayer de copier-coller ce qu'ils ont dit.

Si vous, ou quelqu'un d'autre veut vraiment faire cela (convertir int [] à objet [] ) Pour une raison quelconque, vous pouvez utiliser linq comme: xxx

;)


2 commentaires

Il pourrait y avoir beaucoup de solutions de contournement. S'il vous plaît voir la réponse de 'gabe' ci-dessous


Pourquoi pas simplement utiliser array.copy ? msdn.microsoft.com/en-us/library/system. Array.copy.aspx