2010-09-08 17 views
12

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

supongo que dependerá de la aplicación. eche un vistazo dentro de la clase de cuerda con reflector – knittl

+3

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 :) –

Respuesta

14

No, no es una matriz. Pero tiene un indexador. Lo mejor de ambos mundos.

+0

elástico? Qué significa eso? – recursive

+1

Elástico, como una banda elástica. BoltClock

+1

Quiero decir que no tiene que declararlo con el tamaño fijo. –

1

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.

2

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.

3

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

+4

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

+0

Se llama intercesión de cuerdas. –

+0

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'. –

1

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.

+2

Esto es un poco inexacto. Un 'IEnumerable ' no es lo que permite que el indexador se use en cadenas. Si necesita acceder a un elemento desde cualquier 'IEnumerable ' tendría que usar el elemento 'ElementAt' m ethod; un indexador no estaría disponible para otros tipos de objetos ('T') simplemente implementando' IEnumerable '. –

2

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.

17

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.

5

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.

0

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.

1

Cadenas no es simplemente una matriz, en el sentido de que "Hello" is char[] se evalúa a false.

2

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.

2

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; } 
+0

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

+1

@AndrasDeak Gracias por su comentario, he editado mi respuesta. –

+0

Espléndido, gracias. –

Cuestiones relacionadas