Como el código siguiente es posible en C#, estoy trayectos si la cadena es en realidad un conjunto de caracteres:C# - ¿la cadena realmente es una matriz de caracteres o solo tiene un indexador?
string a="TEST";
char C=a[0]; // will be T
Como el código siguiente es posible en C#, estoy trayectos si la cadena es en realidad un conjunto de caracteres:C# - ¿la cadena realmente es una matriz de caracteres o solo tiene un indexador?
string a="TEST";
char C=a[0]; // will be T
A string
no es una matriz de char
s hasta que la convierta en una. La notación simplemente se usa para acceder a caracteres en diferentes posiciones (índices) en una cadena.
A string
no es un char[]
, aunque sí tiene un .ToCharArray()
. También tiene un indexador, que le permite acceder a los caracteres individualmente, como lo ha demostrado. Es probable que se haya implementado con una matriz internamente, pero eso es un detalle de implementación.
No, String es una clase en .Net. Puede estar respaldado por una matriz. pero no es una matriz. Las clases pueden tener indizadores, y eso es lo que String está haciendo.
Ver comentarios para la elaboración de esta declaración: Por lo que entiendo, todas las cadenas se almacenan en un blob común. Debido a esto, "foo" y "foo" apuntan al mismo punto en ese blob ... una de las razones por las que las cadenas son inmutables en C#.
No debe confiar en el hecho de que las cadenas equivalentes son la misma referencia, ya que no creo que esté garantizada en general. – recursive
Se llama intercesión de cuerdas. –
De acuerdo. Nunca confíe en los detalles de implementación interna. Ellos siempre se reservan el derecho de cambiar. Agregué esa nota porque el OP parecía estar interesado en saber cómo funciona 'String'. –
Usando Reflector, podemos ver que la cadena implementa IEnumerable<char>
. Por lo tanto, no es una matriz de caracteres, pero en esencia se puede usar como uno.
public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
EDIT:
La implementación IEnumerable<char>
no significa que el tipo será indexado. No quise transmitir eso. Significa que puedes enumerarlo y usarlo como una colección. Una mejor forma de redactar lo que quería decir es que una cadena no es una matriz de caracteres, sino una colección de caracteres. Gracias por el comentario.
Esto es un poco inexacto. Un 'IEnumerable
Un objeto de cadena contiene un bloque continuo de caracteres, al igual que una matriz de caracteres, pero el objeto de cadena no es ni contiene un objeto de matriz.
El compilador sabe que la cadena de caracteres es inmutable, por lo que puede hacer ciertas optimizaciones cuando se accede a una cadena, de la misma manera que hace las optimizaciones cuando se accede a una matriz. Por lo tanto, cuando accede a una cadena por índice, es probable que el código termine accediendo directamente a los datos de cadena en lugar de llamar a una propiedad del indexador.
System.String no es una matriz de .NET de Char porque este:
char[] testArray = "test".ToCharArray();
testArray[0] = 'T';
compilará, pero esto:
string testString = "test";
testString[0] = 'T';
no lo hará. Las matrices de Char son mutables, las cadenas no. Además, string is Array
devuelve falso, mientras que char[] is Array
devuelve verdadero.
Las cadenas en .NET están respaldadas por la clase System.String
, que internamente utiliza una serie de métodos inseguros para manipular el puntero en los datos de cadena reales utilizando técnicas de manipulación de memoria C estándar.
La clase String
en sí no contiene una matriz, pero tiene una propiedad de indexador que le permite tratar los datos como si fuera una matriz.
Todo el mundo ha dado la mitad de la respuesta, asi que aquí hay dos partes:
1) En sentido estricto, sí, una cadena en .NET es un conjunto de caracteres. Lo es tanto en su implementación interna como en la definición de una matriz.
2) Sin embargo, String es, como han señalado otros, algo peculiar. No es un System.Array como todas las demás matrices. Entonces, en la forma estricta específica de .NET, una cadena no es una matriz.
Cadenas no es simplemente una matriz, en el sentido de que "Hello" is char[]
se evalúa a false
.
Para agregar un poco a la respuesta de Scott Dorman y Gufa. Si usa Windbg y! DumpObject en la cadena 'abcd' obtendrá algo como esto.
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 <<
Notarás que solo tiene tres campos de instancia. m_arrayLength, m_stringLength y m_firstChar. No contiene una instancia System.Char [] Los otros 2 campos son compartidos estáticos, por lo que cada System.String tiene la misma cadena vacía y WhitespaceChar Char Array.
Si sigues eso con un DumpByte verás los datos de cadena (en este caso abcd) que están en el montón que por supuesto comienza en offset 0x0c (m_firstChar) y tiene 8 bytes de ancho (m_stringLength 4 x 2 para 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 usted fuera a mirar en el SSCLI verá que, como dice Scott, o bien ejecuta el código inseguro y utiliza técnicas de puntero para leer los datos utilizando el m_firstChar y la m_stringLength.
La cadena es una clase que toma una matriz de caracteres para inicializarse a sí misma, de modo que cuando intenta buscar el elemento en algún índice, devuelve char. Compruebe la clase string
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);
}
Véase también declaración de la clase de cadena.
public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
que se hereda por IEnumerable<char>
.
Dentro de la clase de cadena hay una propiedad get que devuelve el carácter cuando se pasa el índice, vea la imagen. Que dice claramente que Obtiene el objeto System.Char en una posición especificada en el System.String actual
public char this[int index] { get; }
No responda las cosas con el código incluido como imágenes. En cuanto a su respuesta, debería funcionar perfectamente si copia esos bloques de código correctamente a la respuesta. –
@AndrasDeak Gracias por su comentario, he editado mi respuesta. –
Espléndido, gracias. –
supongo que dependerá de la aplicación. eche un vistazo dentro de la clase de cuerda con reflector – knittl
Es una buena idea no molestar cómo se representa internamente la cuerda. La implementación de Microsoft puede diferir de la de Mono, que puede diferir del Programa Marco Compacto ... Programa contra la (s) interfaz (es) y no para las internas :) –