Question C # - est une chaîne en fait un tableau de caractères ou a-t-il juste un indexeur?


Comme le code suivant est possible en C #, je suis intéressé à savoir si string est en fait un tableau de caractères:

string a="TEST";
char C=a[0]; // will be T

12
2017-09-08 15:14


origine


Réponses:


System.String n'est pas un tableau .NET de Char car ceci:

char[] testArray = "test".ToCharArray();

testArray[0] = 'T';

compilera, mais ceci:

string testString = "test";

testString[0] = 'T';

ne sera pas. Les tableaux de caractères sont mutables, les chaînes ne le sont pas. Aussi, string is Array renvoie false, alors que char[] is Array renvoie vrai.


17
2017-09-08 15:34



Non, ce n'est pas un tableau. Mais il a un indexeur. Le meilleur des deux mondes.


14
2017-09-08 15:15



Les chaînes en .NET sont soutenues par le System.String class, qui utilise en interne un ensemble de méthodes peu sûres pour manipuler les pointeurs sur les données de chaîne réelles en utilisant les techniques de manipulation de mémoire C standard.

le String class lui-même ne contient pas de tableau, mais il possède une propriété d'indexeur qui vous permet de traiter les données comme s'il s'agissait d'un tableau.


5
2017-09-08 15:37



Non, String est une classe dans .Net. Il peut être soutenu par un tableau. mais ce n'est pas un tableau. Les classes peuvent avoir des indexeurs, et c'est ce que fait String.

Voir les commentaires pour élaboration sur cette déclaration:  D'après ce que j'ai compris, toutes les chaînes sont stockées dans un blob commun. De ce fait, "foo" et "foo" pointent vers le même point dans cette tâche ... une des raisons pour lesquelles les chaînes sont immuables dans C #.


3
2017-09-08 15:16



UNE string n'est pas un char[], bien qu'il y ait un .ToCharArray(). En outre, il dispose d'un indexeur, qui vous permet d'accéder aux caractères individuellement, comme vous l'avez montré. Il est probable qu’elle a été implémentée en interne avec un tableau, mais c’est un détail d’implémentation.


2
2017-09-08 15:15



Un objet chaîne contient un bloc continu de caractères, tout comme un tableau de caractères, mais l'objet chaîne n'est ni ne contient un objet tableau.

Le compilateur sait que la chaîne de caractères est immuable, elle peut donc effectuer certaines optimisations lorsque vous accédez à une chaîne, de la même manière que lors des optimisations lorsque vous accédez à un tableau. Ainsi, lorsque vous accédez à une chaîne par index, il est probable que le code accède directement aux données de la chaîne au lieu d'appeler une propriété de l'indexeur.


2
2017-09-08 15:33



Pour ajouter un peu à la réponse de Scott Dorman et de Gufa. Si vous utilisez Windbg et! DumpObject sur la chaîne 'abcd', vous obtiendrez quelque chose comme ça.

0:000> !do 01139b24
Name: System.String
MethodTable: 79330a00
EEClass: 790ed64c
Size: 26(0x1a) bytes
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: abcd
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332c4c  4000096        4         System.Int32  1 instance        5 m_arrayLength
79332c4c  4000097        8         System.Int32  1 instance        4 m_stringLength
793316e0  4000098        c          System.Char  1 instance       61 m_firstChar
79330a00  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  00181b38:01131198 <<
79331630  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  00181b38:011318b8 <<

Vous remarquerez qu'il n'y a que trois champs d'instance. m_arrayLength, m_stringLength et m_firstChar. Il ne contient pas d'instance System.Char [] Les 2 autres champs sont statiques partagés, donc chaque System.String a la même chaîne vide et WhitespaceChar Char Array.

Si vous suivez cela avec un DumpByte, vous verrez les données de chaîne (dans ce cas-ci abcd) qui se trouvent dans le tas qui commence bien sûr à l'offset 0x0c (m_firstChar) et a une largeur de 8 octets (m_stringLength 4 x 2 pour unicode).

0:000> db 01139b24 L1A

01139b24  00 0a 33 79 05 00 00 00-04 00 00 00 61 00 62 00  ..3y........a.b.
01139b34  63 00 64 00 00 00 00 00-00 00                    c.d......

Si vous regardez dans le SSCLI, vous verrez que, comme le dit Scott, soit il exécute du code non sécurisé et utilise des techniques de pointeur pour lire les données en utilisant m_firstChar et m_stringLength.


2
2017-09-08 20:17



String est une classe qui prend un tableau de caractères pour s'initialiser. Donc, lorsque vous essayez de récupérer l'élément à un certain index, il retourne char. Vérifiez la classe de chaîne

public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
    {
        // Summary:
        //     Initializes a new instance of the System.String class to the value indicated
        //     by an array of Unicode characters.
        //
        // Parameters:
        //   value:
        //     An array of Unicode characters.
        [SecuritySafeCritical]
        public String(char[] value);
    }

Voir aussi la déclaration de classe String.

public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>

Qui est hérité par IEnumerable<char>.

A l'intérieur de la classe de chaînes, il y a une propriété get qui renvoie le caractère lorsque l'index est transmis, voir l'image. Qui dit clairement que Obtient l'objet System.Char à une position spécifiée dans le System.String en cours

public char this[int index] { get; }

2
2017-07-20 20:21



UNE string n'est pas un tableau de chars jusqu'à ce que vous le convertissiez en un. La notation est simplement utilisée pour accéder à des caractères à différentes positions (index) dans une chaîne.


1
2017-09-08 15:15



En utilisant Réflecteur, on peut voir que cette chaîne est implémentée IEnumerable<char>. Donc, ce n'est pas un tableau de caractères, mais peut être utilisé comme tel.

public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>

MODIFIER:

Exécution IEnumerable<char> ne signifie pas que le type sera indexé. Je ne voulais pas transmettre cela. Cela signifie que vous pouvez l'énumérer et l'utiliser comme une collection. Une meilleure façon de formuler ce que je voulais dire est qu’une chaîne n’est pas un tableau de caractères, mais une collection de caractères. Merci pour le commentaire.


1
2017-09-08 15:32