Подтвердить что ты не робот

С# - строка на самом деле является массивом символов или просто имеет индекс?

Поскольку в С# существует следующий код, я интересуюсь, является ли строка фактически массивом символов:

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

Ответ 1

System.String не является .NET-массивом Char, потому что это:

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

testArray[0] = 'T';

будет компилироваться, но это:

string testString = "test";

testString[0] = 'T';

не будет. Char массивы изменяемы, строки - нет. Кроме того, string is Array возвращает false, а char[] is Array возвращает true.

Ответ 2

Нет, это не массив. Но у него есть указатель. Лучшее из обоих миров.

Ответ 3

Строки в .NET поддерживаются классом System.String, который внутренне использует кучу небезопасных методов для манипуляции указателями по фактическим строковым данным с использованием стандартных методов манипуляции с памятью.

Сам класс String не содержит массив, но имеет свойство индексатора, которое позволяет обрабатывать данные так, как если бы они были массивом.

Ответ 4

Нет, String - это класс в .Net. Он может поддерживаться массивом. но это не массив. Классы могут иметь указатели, и это то, что делает строка.

См. комментарии для разработки этого утверждения: Из того, что я понимаю, все строки хранятся в общем блобе. Из-за этого "foo" и "foo" указывают на ту же самую точку в этом блоке... одна из причин, по которой строки являются неизменными в С#.

Ответ 5

A string не является char[], хотя он имеет .ToCharArray(). Также у него есть индекс, который позволяет вам обращаться к персонажам индивидуально, как вы показали. Вполне вероятно, что он был реализован с массивом внутри, но это деталь реализации.

Ответ 6

Строковый объект содержит непрерывный блок символов, подобно массиву символов, но строковый объект не является и не содержит объект массива.

Компилятор знает, что строковая строка неизменна, поэтому она может делать определенные оптимизации при доступе к строке, так же, как она делает оптимизацию при доступе к массиву. Таким образом, при доступе к строке по индексу, вероятно, что код в конечном итоге обращается к строковым данным напрямую, а не к вызову свойства индексатора.

Ответ 7

Чтобы добавить немного к Скотту Дорману и Гуфе, ответьте. Если вы используете Windbg и! DumpObject в строке 'abcd', вы получите что-то вроде этого.

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 <<

Вы заметите, что у него есть только три поля экземпляра. m_arrayLength, m_stringLength и m_firstChar. Он не содержит экземпляр System.Char []. Другие 2 поля являются статическими, поэтому каждая System.String имеет ту же пустую строку и WhitespaceChar Char Array.

Если вы выполните это с помощью DumpByte, вы увидите строковые данные (в данном случае abcd), которые в куче, которая, конечно, начинается со смещения 0x0c (m_firstChar) и имеет ширину 8 байтов (m_stringLength 4 x 2 для 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......

Если вы заглянете в SSCLI, вы увидите, что, как говорит Скотт, он запускает небезопасный код и использует методы указателей для чтения данных с помощью m_firstChar и m_stringLength.

Ответ 8

String - это класс, который берет массив char для инициализации, поэтому, когда вы пытаетесь извлечь элемент в некоторый индекс, он возвращает char. Проверьте класс строки

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);
    }

Также см. объявление класса String.

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

Наследуется IEnumerable<char>.

Внутри класса string есть свойство get, которое возвращает char при передаче индекса, см. изображение. Что явно говорит, что получает объект System.Char в указанной позиции в текущей System.String

public char this[int index] { get; }

Ответ 9

A string не является массивом char, пока вы не преобразуете его в один. Обозначение просто используется для доступа к символам в разных позициях (индексах) в строке.

Ответ 10

Используя Reflector, мы видим, что строка реализует IEnumerable<char>. Таким образом, это не массив символов, но по существу может быть использован как один.

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

EDIT:

Реализация IEnumerable<char> не означает, что тип будет проиндексирован. Я не хотел этого. Это означает, что вы можете перечислить его и использовать как коллекцию. Лучший способ формулировки я хотел сказать, что строка не является символьным массивом, а представляет собой набор символов. Спасибо за комментарий.

Ответ 11

Строки - это просто не массив, в том смысле, что "Hello" is char[] оценивается как false.

Ответ 12

Каждый дал половину ответа, так что вот обе части:

1) Строго говоря, да, String в .NET - это массив символов. Это происходит как во внутренней реализации, так и благодаря синтаксическому определению массива.

2) Однако String, как отмечали другие, несколько своеобразна. Это не System.Array, как все остальные массивы. Таким образом, в строгом, специфичном .NET способе, String не является массивом.