¿Cuál es la diferencia entre String y string en C #?

6511

Ejemplo ( tenga en cuenta el caso ):

string s = "Hello world!";
String s = "Hello world!";

¿Cuáles son las pautas para el uso de cada uno? ¿Y cuáles son las diferencias?

Peter O.
fuente
72
@ORMapper, pero el hecho es que stringes una construcción léxica de la gramática de C #, mientras que System.Stringes solo un tipo. Independientemente de cualquier diferencia explícita mencionada en cualquier especificación, todavía existe esta diferencia implícita que podría ser acomodada con cierta ambigüedad. El lenguaje en sí mismo debe soportar stringde manera que la implementación no esté (tan) tan obligada a considerar para una clase particular en el BCL.
Kirk Woll
106
@KirkWoll: Según la especificación del lenguaje, el lenguaje en sí debe considerarse stringexactamente igual al tipo BCL System.String, nada más. Eso no es ambiguo en absoluto. Por supuesto, puede implementar su propio compilador, utilizando la gramática de C #, y utilizar todos los tokens que se encuentran así para algo arbitrario, no relacionado con lo que se define en la especificación del lenguaje C #. Sin embargo, el lenguaje resultante solo sería similar a C #, no podría considerarse C #.
O Mapper
88
Puede usar stringsin una directiva de uso para el Sistema. No puedes hacer eso con String.
Wilsu
14
Para alguien que viene de Algol y Fortran, esta discusión muestra que algo anda mal string. Es necesario abreviar System.String, pero, como un alias, parece bastante, pero no exactamente lo mismo. Después de varios años de C #, sin embargo, yo diría, es seguro de usar, simplemente stringy string.Format()no que preocuparse por System.String.
Roland
8
@Sangeeta ¿Qué estás diciendo? La System.Stringclase todavía está allí, y la stringpalabra clave sigue siendo un alias para ella. Justo como System.Int32y int. Son literalmente lo mismo.
Craig

Respuestas:

6107

stringes un alias en C # para System.String.
Entonces, técnicamente, no hay diferencia. Es como int vs System.Int32 .

En cuanto a las pautas, generalmente se recomienda usar stringcada vez que se refiera a un objeto.

p.ej

string place = "world";

Del mismo modo, creo que generalmente se recomienda usar Stringsi necesita referirse específicamente a la clase.

p.ej

string greet = String.Format("Hello {0}!", place);

Este es el estilo que Microsoft tiende a usar en sus ejemplos .

Parece que la orientación en esta área puede haber cambiado, ya que StyleCop ahora impone el uso de los alias específicos de C #.

Derek Park
fuente
163
Si decides usar StyleCop y seguir eso, eso indicará usar los tipos específicos del idioma. Entonces, para C #, tendrá cadena (en lugar de String), int (en lugar de Int32), float (en lugar de Single) - stylecop.soyuz5.com/SA1121.html
Dominic Zukiewicz
144
Siempre uso los alias porque supuse que algún día podría ser útil porque actúan como una abstracción, por lo que pueden cambiar sus implementaciones sin que yo tenga que saberlo.
Rob el
37
Visual Studio 2015 dice que String.Format debería cambiarse a string.Format, así que supongo que Microsoft va por ese camino. También siempre he usado String para los métodos estáticos.
Sami Kuhmonen
32
Al leer esto, noté que varios de los comentarios son simplemente incorrectos. @ DRAirey1 Con el tiempo, descubrirás que la forma antigua sigue siendo la mejor, si dudas de eso, te reto a que intentes escribir código C # sin usar Visual Studio. Es prácticamente imposible y una situación que surge de vez en cuando en el trabajo de desarrollo web. @Vlad No necesita importar nada para usar String. @Abhi Tu comentario no tiene sentido y es igualmente cierto para string.Format(). @KlitosG No, eso no es cierto. Todos funcionan exactamente igual.
krowe2
46
¿Podría agregar una observación de que, de hecho, hay una diferencia? Por ejemplo: nameof(string)no compilará mientras que lo nameof(String)hará.
Jeroen Vannevel
3440

Solo por completo, aquí hay un volcado de información relacionada ...

Como otros han señalado, stringes un alias para System.String. Se compilan con el mismo código, por lo que en el momento de la ejecución no hay diferencia alguna. Este es solo uno de los alias en C #. La lista completa es:

object:  System.Object
string:  System.String
bool:    System.Boolean
byte:    System.Byte
sbyte:   System.SByte
short:   System.Int16
ushort:  System.UInt16
int:     System.Int32
uint:    System.UInt32
long:    System.Int64
ulong:   System.UInt64
float:   System.Single
double:  System.Double
decimal: System.Decimal
char:    System.Char

Aparte de stringy object, los alias son todos para valorar tipos. decimales un tipo de valor, pero no un tipo primitivo en el CLR. El único tipo primitivo que no tiene un alias es System.IntPtr.

En la especificación, los alias de tipo de valor se conocen como "tipos simples". Los literales se pueden usar para valores constantes de cada tipo simple; ningún otro tipo de valor tiene formas literales disponibles. (Compare esto con VB, que permite DateTimeliterales y también tiene un alias).

Hay una circunstancia en la que tiene que utilizar los alias: al especificar explícitamente el tipo subyacente de una enumeración. Por ejemplo:

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid

Eso es sólo una cuestión de la forma en la especificación define enumeración declaraciones - la parte después de los dos puntos tiene que ser el de tipo integral de producción, que es una muestra de sbyte, byte, short, ushort, int, uint,long , ulong, char... en lugar de un tipo de producción, utilizado por las declaraciones de variables, por ejemplo. No indica ninguna otra diferencia.

Finalmente, cuando se trata de qué usar: personalmente uso los alias en todas partes para la implementación, pero el tipo CLR para cualquier API. Realmente no importa demasiado lo que use en términos de implementación: la consistencia entre su equipo es agradable, pero a nadie más le importará. Por otro lado, es realmente importante que si se refiere a un tipo en una API, lo haga de forma neutral en cuanto al idioma. Un método llamado ReadInt32no es ambiguo, mientras que un método llamado ReadIntrequiere interpretación. La persona que llama podría estar usando un lenguaje que define un intalias para Int16, por ejemplo. Los diseñadores marco .NET han seguido este patrón, buenos ejemplos de estar en las BitConverter, BinaryReadery Convertlas clases.

Jon Skeet
fuente
82
La situación de herencia con enum es interesante. ¿Puede señalar la documentación sobre por qué se debe usar el alias para las enumeraciones? ¿O es un error conocido?
JaredPar
149
Está en la sección 14.1 de la especificación (no puedo citar aquí fácilmente porque es demasiado largo). No dice explícitamente que tienes que usar el alias, pero los alias son una especie de tratado como a sus propios tipos. Todo es un poco raro.
Jon Skeet
32
@PiPeep Lo que es más sorprendente que la gran cantidad de votos a favor es la asombrosa cantidad baja de votos a favor (considere que las 5 publicaciones principales tienen un total de más de 2000 votos a favor y, sin embargo, solo 1 voto a favor entre todos). Especialmente cuando tienes en cuenta la noción de que siempre hay "enemigos" en cualquier comunidad, realmente me parece increíble.
corsiKa
40
Una diferencia interesante entre stringy Stringes que string' is a keyword in c#, so you can not use it as a variable name.For Ex: string string = "hi"; //compiler error, but String String = "hi"; `es aceptable, ya que Stringes un identificador, no una palabra clave.
Sanjeev Rai
33
@SanjeevRai: Sí. Puede usar @stringpara crear un identificador que termine como stringsi así fuera. Es una especie de mecanismo de escape.
Jon Skeet
716

Stringsignifica System.Stringy es un tipo de .NET Framework. stringes un alias en el lenguaje C # para System.String. Ambos están compilados System.Stringen IL (lenguaje intermedio), por lo que no hay diferencia. Elige lo que te gusta y úsalo. Si codifica en C #, preferiría stringque sea un alias de tipo C # y bien conocido por los programadores de C #.

Puedo decir lo mismo sobre ( int, System.Int32) etc.

artur02
fuente
3
`Si codifica en C #, preferiría una cadena, ya que es un alias de tipo C # y bien conocido por los programadores de C #`, cuando una persona de C # no conocería el marco .NET. +1 como creo que generalmente es la mejor respuesta, pero el punto que menciono parece extraño.
MyDaftQuestions
44
Personalmente prefiero usar "Int32", ya que muestra inmediatamente el rango del valor. Imagine si actualizaran el tipo de "int" en sistemas posteriores de bits superiores. Aparentemente, 'int' en c se ve como "el tipo entero con el que el procesador de destino es más eficiente trabajando" , y se define como "al menos 16 bits". Prefiero una consistencia predecible allí, muchas gracias.
Nyerguds
2
@MyDaftQuestions Estoy de acuerdo. En todo caso, tendría sentido usar los tipos .net de manera consistente porque ignoran el idioma y el tipo es obvio, independiente de cualquier idioma (¿conozco todas las idiosincrasias de F # o VB?).
Peter - Restablece a Mónica el
55
@Nyerguds Hay dos razones para simplemente no preocuparse por eso. Una es que intse define en la especificación del lenguaje C # como un entero de 32 bits, independientemente del hardware. C #, a pesar de una herencia compartida en las brumas del tiempo, en realidad no es C. Cambiar inta un entero de 64 bits sería un cambio radical en la especificación y el idioma. También requeriría redefinir long, ya longque actualmente es el entero de 64 bits. La otra razón para no preocuparse es irrelevante ya que los tipos nunca cambiarán, pero .NET es lo suficientemente abstracto como para que el 99% del tiempo no tenga que pensar en ello de todos modos. ;-)
Craig
55
@Craig cavo en lotes de formatos de juego de propiedad de edad en la que no tengo que pensar en eso todo el tiempo, sin embargo. Y luego usar Int16, Int32y Int64es mucho más transparente en el código que usar el no shortintlong
descriptivo
506

La mejor respuesta que he escuchado sobre el uso de los alias de tipo proporcionados en C # proviene de Jeffrey Richter en su libro CLR Via C # . Aquí están sus 3 razones:

  • He visto a varios desarrolladores confundidos, sin saber si usar string o String en su código. Debido a que en C # la cadena (una palabra clave) se asigna exactamente a System.String (un tipo de FCL), no hay diferencia y se puede usar.
  • En C #, long se asigna a System.Int64 , pero en un lenguaje de programación diferente, long podría asignarse a Int16 o Int32 . De hecho, C ++ / CLI de hecho trata durante mucho tiempo como un Int32 . Alguien que lea el código fuente en un idioma podría malinterpretar fácilmente la intención del código si estuviera acostumbrado a programar en un lenguaje de programación diferente. De hecho, la mayoría de los idiomas ni siquiera tratar larga como palabra clave y no el código de compilación que lo utiliza.
  • El FCL tiene muchos métodos que tienen nombres de tipo como parte de sus nombres de método. Por ejemplo, el tipo BinaryReader ofrece métodos como ReadBoolean , ReadInt32 , ReadSingle , etc., y el tipo System.Convert ofrece métodos como ToBoolean , ToInt32 , ToSingle , etc. Aunque es legal escribir el siguiente código, la línea con flotante me parece muy poco natural, y no es obvio que la línea sea correcta:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Entonces ahí lo tienes. Creo que todos estos son puntos realmente buenos. Sin embargo, no me encuentro usando los consejos de Jeffrey en mi propio código. Tal vez estoy demasiado atascado en mi mundo C # pero termino tratando de hacer que mi código se vea como el código marco.

Luke Foust
fuente
24
El segundo punto suena realmente como una razón para no usar string, intetc.
MauganRa
15
@MauganRa Y se supone que el autor del libro enumera esas razones por las cuales no usa alias.
tomi.lee.jones
31
"Si alguien lee el código fuente de C #, debe interpretarlo de acuerdo con las especificaciones del idioma, no con las especificaciones de otros idiomas". Eso pierde el punto por completo. No es que alguien tenga la intención de malinterpretar el código, es simplemente fácil para el cerebro llegar a la conclusión equivocada cuando un tipo tiene un significado diferente al que el programador ve a diario en otro contexto. Todos cometemos errores; El uso de tipos explícitamente nombrados hace que esos errores sean menos probables.
Darryl
10
+ Estas razones resumen mis sentimientos al respecto. Cuando comencé a codificar en C # (proveniente de un fondo Java / C ++ / C), pensé que los alias eran feos. Todavía me siento así, desafortunadamente la mayor parte del mundo no parece estar de acuerdo conmigo, o no les importa, y por eso utilizo las minúsculas.
gusgorman
8
@jinzai la pregunta es sobre C #, en el que longse define como un entero de 64 bits con signo, independientemente de la plataforma o el compilador. Por lo que en algunos casos al menos, eso sí, que no depende de la lengua.
phoog
456

stringes una palabra reservada, pero Stringes solo un nombre de clase. Esto significa que stringno se puede usar como un nombre de variable por sí mismo.

Si por alguna razón quisieras una variable llamada cadena , solo verías la primera de estas compilaciones:

StringBuilder String = new StringBuilder();  // compiles
StringBuilder string = new StringBuilder();  // doesn't compile 

Si realmente desea un nombre de variable llamado cadena , puede usarlo @como prefijo:

StringBuilder @string = new StringBuilder();

Otra diferencia crítica: Stack Overflow los resalta de manera diferente.

Simon_Weaver
fuente
20
Tenga en cuenta que llamar a un local no @stringtiene mucho sentido, ya que los nombres de los locales solo están presentes en los PDB. También podría llamarlo _stringo algo así. Tiene más sentido para cosas que tienen nombres accesibles a través de la reflexión, donde @stringestaría el nombre de un miembro "string".
Roman Starkov
25
También tenga en cuenta que usar una palabra reservada como nombre de variable es muy poco elegante.
Elton
77
El OP no quiere usar String o string como nombre de variable. Pidieron una explicación de la diferencia entre estos tipos . Su respuesta solo sirve para agregar más confusión OMI
Matt Wilko
1
@craig si estuvieras escribiendo software para enseñarle a la gente cómo hacer nudos?
Simon_Weaver
55
@Simon_Weaver nudos en cuerdas? jaja bueno. :-) Por supuesto, puede elegir un nombre alternativo, como hilo. Espera un minuto ... ¡Oh!
Craig
392

Hay una diferencia : no se puede usar Stringsin using System;antes.

usuario3296
fuente
14
de manera predeterminada, la mayoría de las personas agrega esto de alguna manera en la parte superior del archivo. ¡VS hace esto por defecto en la mayoría de los casos de no todos!
IbrarMumtaz
99
Por defecto agrego solo las usingdeclaraciones que necesito y elimino explícitamente todo lo que no. Herramientas de productividad de energía> "[x] Eliminar y formatear usos al guardar"
JMD
2
@JMD ¡He modificado el archivo de plantilla .cs para que ni siquiera tenga declaraciones de uso en la parte superior! También cambié la plantilla de clase a internal sealed.
ErikE
@JMD Odio esa característica. A veces realiza cambios en archivos que no se han tocado, lo que dificulta ver qué cambios reales contiene un conjunto de cambios. Por supuesto, generalmente elimino "el uso de spam", pero solo de forma activa, no automática.
mg30rg
Puede ser así para C #, pero no para todos los lenguajes .NET. (Powershell importa el espacio de nombres del sistema de forma predeterminada.)
FSCKur
312

Ha sido cubierto arriba; sin embargo, no puedes usar stringen la reflexión; debes usar String.

TraumaPony
fuente
66
No entiendo lo que significa esta respuesta y por qué fue votada. Puedes usar typeof(string)en la reflexión. Ejemplo uno: if (someMethodInfo.ReturnType == typeof(string)) { ... }Ejemplo dos: var p = typeof(string).GetProperty("FirstChar", BindingFlags.NonPublic | BindingFlags.Instance);¿Dónde es lo que debe usar String, no string? Si intenta cosas como Type.GetType("String")o Type.GetType("string"), tampoco encontrará la clase porque falta el espacio de nombres. Si por alguna tonta razón comparas .Nameun tipo con "string"mayúsculas y minúsculas, tienes razón.
Jeppe Stig Nielsen
257

System.Stringes la clase de cadena .NET, en C # stringes un alias para System.String, por lo que en uso son lo mismo.

En cuanto a las pautas, no me atascaría demasiado y solo usaría lo que desee: hay cosas más importantes en la vida y el código será el mismo de todos modos.

Si ustedes se encuentran la construcción de sistemas en los que es necesario especificar el tamaño de los enteros que está utilizando y por lo que tienden a usar Int16, Int32, UInt16, UInt32etc, entonces puede ser que parezca más natural de utilizar String- y cuando tenga que desplazarse entre diferentes lenguajes .NET que podría hacer las cosas más comprensibles; de lo contrario, usaría string e int.

Ronnie
fuente
2
Solo elige uno y sé consistente. Si trabaja en algún lugar con un estilo de casa, úselo.
Alan B
3
desafortunadamente, el estilo es una preferencia personal y puede ser demasiado costoso para aplicar en una base de código grande en varios equipos sin un propietario de código dedicado. siempre hay asuntos más importantes que atender en lugar de string vs String. lo que nos lleva de vuelta a "cosas más importantes en la vida"
aiodintsov
Esto es definitivamente una cosa de preferencia; por ejemplo: Yo prefiero usar short, int, ushort, uinten lugar de Int16, etc. Sobre todo porque esta es la forma en que aprendí. Por supuesto, Int16es más fácil de entender de inmediato para aquellos con menos experiencia. +1 De mi parte!
Candleshark
211

Prefiero los .NETtipos en mayúscula (en lugar de los alias) por razones de formato. Los .NETtipos tienen el mismo color que otros tipos de objetos (los tipos de valor son objetos adecuados, después de todo).

Las palabras clave condicionales y de control (como if, switchy return) son minúsculas y de color azul oscuro (de forma predeterminada). Y preferiría no tener el desacuerdo en el uso y el formato.

Considerar:

String someString; 
string anotherString; 
StuartLC
fuente
11
¿También escribes código como: Int32 i = 1; En lugar de int i = 1; ? Parece inconsistente no usar el alias de cadena cuando está disponible.
bytedev
29
@nashwan: en realidad, sí, utilizo en Int32 i=1;lugar de int i = 1; encontrar que el primero es más legible en cuanto a mi intención: es decir, que quiero un entero con signo de 32 bits.
NotMe
55
Bueno, supongo que todo depende de si el desarrollador cree que está escribiendo código C # (cadena) o código .NET (cadena). Personalmente, creo que estoy escribiendo C # (y es C # que está usando .NET).
bytedev
77
@ Alex: mi punto era simplemente que prefiero ser muy específico en mi codificación para eliminar la ambigüedad.
NotMe
22
En el otro extremo del espectro, casi siempre usovar
tic el
193

stringy Stringson idénticos en todos los sentidos (excepto la "S" mayúscula). No hay implicaciones de rendimiento de ninguna manera.

stringSe prefiere la minúscula en la mayoría de los proyectos debido al resaltado de sintaxis

TheSoftwareJedi
fuente
Jeffrey Richter recomienda usar el tipo CLR en todos los casos (CLR a través de C #) para evitar exactamente el tipo de confusión que está teniendo lugar aquí.
Josh
Claramente, si usas S o s habrá causado estas preguntas, así que vota a Richter. ;)
Brad Wilson
Richter significaba que la cadena no debería haber sido una opción: Microsoft no debería tenerla en el idioma. No puedes menospreciar a Richter, ¡es una leyenda! :)
Joe Ratzer
1
Estoy de acuerdo en que podría haber sido mejor no tener los alias en absoluto. Pero dado que los tenemos, creo que está bien usarlos (pero no en nombres de métodos, etc.)
Jon Skeet
10
"string" no es lo mismo que "String". Es significa "System.String". Entonces, si usa "String", debe poner "using System" para incluir el espacio de nombres
ThiagoAlves
186

C # es un lenguaje que se usa junto con el CLR.

string es un tipo en C #.

System.String es un tipo en el CLR.

Cuando use C # junto con el CLR stringse asignará a System.String.

Teóricamente, podría implementar un compilador C # que generó el código de bytes de Java. Una aplicación sensata de este compilador probablemente mapa stringa java.lang.Stringfin de interoperar con la biblioteca de tiempo de ejecución de Java.

Rasmus Faber
fuente
1
stringno es un tipo en C #; es una palabra reservada que se asigna a un tipo en el CLR.
CesarGon
@CesarGon: Según ECMA-334, sección 8.2.1: "C # proporciona un conjunto de tipos predefinidos [...] Los tipos de referencia predefinidos son objeto y cadena".
Rasmus Faber
10
De acuerdo con ECMA-334, sección 9.4.3, "cadena" es una palabra clave. :-) Estoy de acuerdo con usted en que "cadena" es un tipo si se enfoca en la semántica, pero diría que es una palabra clave (es decir, una palabra reservada) si se enfoca en la sintaxis. El estándar respalda ambos puntos de vista (¡quizás demasiado ambiguo!). Para mí, el OP se trata de sintaxis, por lo que tiendo a centrarme en la sintaxis cuando miro las respuestas, pero también veo su punto. Además, su respuesta, tal como está, puede interpretarse en el sentido de que existen dos tipos diferentes: string y String, cuando ese no es el caso. Uno es un mapeo para el otro.
CesarGon
Seamos claros sobre esto. 'string' es un alias reservado. No es un verdadero tipo de datos. Es algo que apunta a otra cosa. Puede eliminar todos estos alias (o simplemente nunca usarlos) y tener un lenguaje de programación perfectamente bueno.
Quarkly
169

Este YouTube video de demuestra prácticamente cómo se diferencian.

Pero ahora para una larga respuesta textual.

Cuando hablamos de que .NEThay dos cosas diferentes, una hay un .NETmarco y la otra hay idiomas ( C#, VB.NETetc.) que usan ese marco.

ingrese la descripción de la imagen aquí

" System.String" aka "String" ("S" mayúscula) es un .NETtipo de datos de marco mientras que "string" es un C#tipo de datos.

ingrese la descripción de la imagen aquí

En resumen "String" es un alias (la misma cosa llamada con diferentes nombres) de "string". Entonces, técnicamente, las dos declaraciones de código a continuación darán el mismo resultado.

String s = "I am String";

o

string s = "I am String";

Del mismo modo, hay alias para otro tipo de datos de C # como se muestra a continuación: -

object:, System.Objectstring:, System.Stringbool:, System.Booleanbyte:, System.Bytesbyte:, System.SByteshort: System.Int16y así sucesivamente

Ahora la pregunta del millón de dólares desde el punto de vista del programador Entonces, ¿cuándo usar "String" y "string"?

Lo primero para evitar confusiones es usar uno de ellos constantemente. Pero desde la perspectiva de las mejores prácticas, cuando se hace una declaración de variables, es bueno usar "cadena" (pequeña "s") y cuando se usa como un nombre de clase, se prefiere "Cadena" ("S" mayúscula).

En el siguiente código, el lado izquierdo es una declaración variable y se declara usando "string". En el lado derecho estamos llamando a un método para que "String" sea más sensible.

string s = String.ToUpper() ;
Shivprasad Koirala
fuente
25
"En resumen" String "es un alias (lo mismo llamado con diferentes nombres) de" string "". Esto no es correcto: el alias es "cadena".
Xavier Egea
3
cuando haces una declaración de variables, es bueno usar "string" (pequeña "s") y cuando lo estás usando como un nombre de clase, se prefiere "String" (mayúscula "S"). Esta convención parece no ser más válida: si usa Visual Studio 2015 y trata de escribirlo String, sugiera que "simplifique su código", llevándolo a string...
Massimiliano Kraus
166

La minúscula stringes un alias para System.String. Son lo mismo en C#.

Hay un debate sobre si se debe utilizar el tipo de sistema ( System.Int32, System.String, etc.) o el tipoC# aliases ( int, string, etc.). Personalmente, creo que deberías usar el C# aliases, pero esa es solo mi preferencia personal.

urini
fuente
44
Ese es el problema, no son alias 'C #', son alias 'C'. No hay 'string' o 'int' nativo en el lenguaje C #, solo azúcar sintáctico.
Quarkly
16
no estoy seguro de dónde vino "C", ya que la especificación del lenguaje C # 5 dice "La cadena de palabras clave es simplemente un alias para la clase predefinida System.String". en la página 85, apartado 4.2.4. Todos los lenguajes de alto nivel son azúcar sintáctica sobre conjuntos de instrucciones de CPU y bytecode.
aiodintsov
157

stringes solo un alias para System.String. El compilador los tratará de manera idéntica.

La única diferencia práctica es el resaltado de sintaxis como mencionas, y que tienes que escribir using Systemsi lo usas String.

Hallgrim
fuente
No necesita prefijar Sistema para usar String.
Joe Ratzer
18
Debe incluir un using Systemal usar String, de lo contrario obtendrá el siguiente error:The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
Ronald
144

Ambos son lo mismo. Pero desde la perspectiva de las pautas de codificación es mejor usar en stringlugar de String. Esto es lo que generalmente usan los desarrolladores. por ejemplo, en lugar de usar Int32, usamos intcomo intes aliasInt32

FYI "La cadena de palabras clave es simplemente un alias para la clase predefinida System.String". - Especificación del lenguaje C # 4.2.3 http://msdn2.microsoft.com/En-US/library/aa691153.aspx

Pradeep Kumar Mishra
fuente
121

Como dicen los demás, son lo mismo. StyleCop reglas, por defecto, harán cumplir su uso stringcomo un estilo de código C # las mejores prácticas, excepto cuando se hace referencia System.Stringfunciones estáticas, tales como String.Format, String.Join, String.Concat, etc ...

Lloyd Cotten
fuente
44
No sabía que StyleCop marcaría el uso de String, excepto por los métodos estáticos. Creo que es genial, ya que así es como siempre lo uso: cadena para declaraciones de tipo y cadena cuando accedo a los miembros estáticos.
Goyuix
102

Nueva respuesta después de 6 años y 5 meses (dilación).

Si bien stringes una palabra clave reservada de C # que siempre tiene un significado fijo, Stringes solo un identificador ordinario que podría referirse a cualquier cosa. Dependiendo de los miembros del tipo actual, el espacio de nombres actual y las usingdirectivas aplicadas y su ubicación, Stringpodrían ser un valor o un tipo distinto deglobal::System.String .

Proporcionaré dos ejemplos donde las usingdirectivas no ayudarán .


Primero, cuando Stringes un valor del tipo actual (o una variable local):

class MySequence<TElement>
{
  public IEnumerable<TElement> String { get; set; }

  void Example()
  {
    var test = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
  }
}

Lo anterior no se compilará porque IEnumerable<>no tiene un miembro no estático llamado Formaty no se aplican métodos de extensión. En el caso anterior, aún es posible usarlo Stringen otros contextos donde un tipo es la única posibilidad sintáctica. Por ejemplo, String local = "Hi mum!";podría estar bien (dependiendo del espacio de nombres y las usingdirectivas).

Peor aún: String.Concat(someSequence)es probable que decir (dependiendo de usings) vaya al método de extensión Linq Enumerable.Concat. No irá al método estático string.Concat.


En segundo lugar, cuando Stringes otro tipo , anidado dentro del tipo actual:

class MyPiano
{
  protected class String
  {
  }

  void Example()
  {
    var test1 = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
    String test2 = "Goodbye";
  }
}

Ninguna de las declaraciones en el Examplemétodo compila. Aquí Stringes siempre un piano cadena , MyPiano.String. Ningún miembro ( statico no) Formatexiste en él (o se hereda de su clase base). Y el valor "Goodbye"no se puede convertir en él.

Jeppe Stig Nielsen
fuente
44
Supongo que para ser diabólico uno podría: using String = System.Int32; using Int32 = System.String; y luego contar los errores.
Steve
77
Esta es la respuesta correcta. stringes System.String. StringPodría ser cualquier cosa.
Dave Cousineau
De acuerdo @DaveCousineau: ese es el punto del alias. Puede crear otro Stringtipo que no se establecería en el objeto System.String. Echa un vistazo: blog.paranoidcoding.com/2019/04/08/…
Kristopher
"La palabra clave stringtiene un significado concreto en C #. Es el tipo System.Stringque existe en el ensamblaje central de tiempo de ejecución. El tiempo de ejecución comprende intrínsecamente este tipo y proporciona las capacidades que los desarrolladores esperan stringsen .NET. Su presencia es tan crítica para C # que si ese tipo no funciona no existe, el compilador saldrá antes de intentar incluso analizar una línea de código. Por lo tanto, stringtiene un significado preciso e inequívoco en el código C #. StringAunque el identificador no tiene un significado concreto en C #. Es un identificador que pasa por todas las reglas de búsqueda de nombres como Widget, Studentetc ... "
Kristopher
3
Diskussed en Meta: meta.stackoverflow.com/questions/385304/…
Patrick Artner
88

Frente a lo que parece ser una práctica común entre otros programadores, prefiero Stringsobrepasar string, solo para resaltar el hecho de que Stringes un tipo de referencia, como mencionó Jon Skeet.

RolandK
fuente
78

Solo me gustaría agregar esto a la respuesta de lfousts, del libro de Ritchers:

La especificación del lenguaje C # establece: "Como cuestión de estilo, se favorece el uso de la palabra clave sobre el uso del nombre completo del tipo de sistema". No estoy de acuerdo con la especificación del lenguaje; Prefiero usar los nombres de tipo FCL y evitar por completo los nombres de tipo primitivos. De hecho, desearía que los compiladores ni siquiera ofrecieran los nombres de tipo primitivos y forzaran a los desarrolladores a utilizar los nombres de tipo FCL. Aquí están mis razones:

  • He visto a varios desarrolladores confundidos, sin saber si usar string o String en su código. Debido a que en la cadena C # (una palabra clave) se asigna exactamente a System.String (un tipo FCL), no hay diferencia y tampoco se puede usar. De manera similar, escuché que algunos desarrolladores dicen que int representa un número entero de 32 bits cuando la aplicación se ejecuta en un sistema operativo de 32 bits y que representa un número entero de 64 bits cuando la aplicación se ejecuta en un sistema operativo de 64 bits. Esta afirmación es absolutamente falsa: en C #, un int siempre se asigna a System.Int32 y, por lo tanto, representa un número entero de 32 bits independientemente del sistema operativo en el que se ejecuta el código. Si los programadores usaranInt32 en su código, entonces esta posible confusión también se elimina.

  • En C #, long se asigna a System.Int64 , pero en un lenguaje de programación diferente, long podría asignarse a Int16 o Int32 . De hecho, C ++ / CLI trata por mucho tiempo como Int32 . Alguien que lea el código fuente en un idioma podría malinterpretar fácilmente la intención del código si estuviera acostumbrado a programar en un lenguaje de programación diferente. De hecho, la mayoría de los idiomas ni siquiera tratar larga como palabra clave y no el código de compilación que lo utiliza.

  • El FCL tiene muchos métodos que tienen nombres de tipo como parte de sus nombres de método. Por ejemplo, el tipo BinaryReader ofrece métodos como ReadBoolean , ReadInt32 , ReadSingle , etc., y el tipo System.Convert ofrece métodos como ToBoolean , ToInt32 , ToSingle , etc. Aunque es legal escribir el siguiente código, la línea con flotante me parece muy poco natural, y no es obvio que la línea sea correcta:

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
  • Muchos programadores que usan C # exclusivamente tienden a olvidar que se pueden usar otros lenguajes de programación contra el CLR, y debido a esto, los mecanismos de C # se deslizan en el código de la biblioteca de clases. Por ejemplo, FCL de Microsoft está casi escrito exclusivamente en C # y desarrolladores en el equipo FCL ahora han introducido métodos en la biblioteca como matriz ‘s GetLongLength , que devuelve un Int64 valor que es un tiempo en C #, pero no en otros idiomas (como C ++ / CLI). Otro ejemplo es el método LongCount de System.Linq.Enumerable .

No entendí su opinión antes de leer el párrafo completo.

Otiel
fuente
72

String ( System.String) es una clase en la biblioteca de clases base. string (minúscula) es un trabajo reservado en C # que es un alias para System.String. Int32 vs int es una situación similar como es Boolean vs. bool. Estas palabras clave específicas del lenguaje C # le permiten declarar primitivas en un estilo similar a C.

Joe Alfano
fuente
67

Stringno es una palabra clave y se puede usar como identificador, mientras que stringes una palabra clave y no se puede usar como identificador. Y en el punto de vista funcional ambos son iguales.

usuario576533
fuente
67

Es una cuestión de convención, de verdad. stringsimplemente se parece más al estilo C / C ++. La convención general es usar cualquier atajo que haya proporcionado el idioma elegido (int / Int para Int32). Esto va para "objeto" y decimaltambién.

Teóricamente, esto podría ayudar a portar código en algún estándar futuro de 64 bits en el que "int" podría significar Int64, pero ese no es el punto, y esperaría que cualquier asistente de actualización cambie cualquier intreferencia de Int32todos modos solo para estar seguro.

Mel
fuente
66

Llegando tarde a la fiesta: uso los tipos CLR el 100% del tiempo (bueno, excepto si me veo obligado a usar el tipo C #, pero no recuerdo cuándo fue la última vez).

Originalmente comencé a hacer esto hace años, según los libros CLR de Ritchie. Tenía sentido para mí que todos los lenguajes CLR finalmente tengan que ser capaces de admitir el conjunto de tipos CLR, por lo que el uso de los tipos CLR proporcionó un código más claro y posiblemente más "reutilizable".

Ahora que lo he estado haciendo durante años, es un hábito y me gusta la coloración que VS muestra para los tipos CLR.

El único inconveniente real es que el autocompletado usa el tipo C #, por lo que termino reescribiendo los tipos generados automáticamente para especificar el tipo CLR.

Además, ahora, cuando veo "int" o "cadena", me parece muy mal, como si estuviera viendo el código C de 1970.

Michael Ray Lovett
fuente
49

No hay diferencia.

La palabra clave C # se stringasigna al tipo .NET System.String: es un alias que cumple con las convenciones de nomenclatura del lenguaje.

Del mismo modo, se intasigna a System.Int32.

Oded
fuente
En una compilación de 64 bits, int se asigna a System.Int64 (8 bytes), en una compilación de 32 bits se asigna a System.Int32 (4 bytes)
Alex
1
IntPtr y UIntPtr son los únicos tipos que cambian de tamaño según la plataforma (sin tener en cuenta los tipos de puntero reales como int*y los tipos compuestos por [U] IntPtrs o punteros reales).
P Daddy
45

Hay una cita sobre este tema del libro de Daniel Solis .

Todos los tipos predefinidos se asignan directamente a los tipos .NET subyacentes. Los nombres de tipo C # (cadena) son simplemente alias para los tipos .NET (String o System.String), por lo que usar los nombres .NET funciona bien sintácticamente, aunque esto se desaconseja. Dentro de un programa C #, debe usar los nombres C # en lugar de los nombres .NET.

usuario2771704
fuente
41

string es una palabra clave y no puede usar string como identificador.

La cadena no es una palabra clave, y puede usarla como identificador:

Ejemplo

string String = "I am a string";

La palabra clave string es un alias, System.Stringaparte del problema de la palabra clave, los dos son exactamente equivalentes.

 typeof(string) == typeof(String) == typeof(System.String)
CoreDeveloper
fuente
2
La única pequeña diferencia es que si usa la clase String, debe importar el espacio de nombres del Sistema en la parte superior de su archivo, mientras que no tiene que hacer esto cuando usa la palabra clave string.
Uttam
Hay casos de uso simples en los que la declaración de igualdad fallaría ... Como definir una cadena de llamada de tipo en el espacio de nombres bla e importar ese espacio de nombres en el archivo en el que se ejecuta la declaración de igualdad.
Rick
40

Sí, no hay diferencia entre ellos, al igual que el booly Boolean.

codificador
fuente
40

@JaredPar (un desarrollador en el compilador de C # y prolífico usuario SO!) Escribió una gran publicación de blog sobre este tema. Creo que vale la pena compartirlo aquí. Es una buena perspectiva sobre nuestro tema.

stringvs. Stringno es un debate de estilo

[...]

La palabra clave stringtiene un significado concreto en C #. Es el tipo System.Stringque existe en el ensamblaje central de tiempo de ejecución. El tiempo de ejecución comprende intrínsecamente este tipo y proporciona las capacidades que los desarrolladores esperan para las cadenas en .NET. Su presencia es tan crítica para C # que si ese tipo no existe, el compilador se cerrará antes de intentar incluso analizar una línea de código. Por lo tanto, stringtiene un significado preciso e inequívoco en el código C #.

Sin Stringembargo, el identificador no tiene un significado concreto en C #. Es un identificador que pasa por todas las reglas de búsqueda de nombres como Widget, Studentetc ... Podría unirse a una cadena o podría unirse a un tipo en otro ensamblado completamente cuyos propósitos pueden ser completamente diferentes a string. Peor aún, podría definirse de tal manera que el código como String s = "hello"; continuó compilando.

class TricksterString { 
  void Example() {
    String s = "Hello World"; // Okay but probably not what you expect.
  }
}

class String {
  public static implicit operator String(string s) => null;
}

El significado real de Stringsiempre dependerá de la resolución del nombre. Eso significa que depende de todos los archivos de origen en el proyecto y de todos los tipos definidos en todos los ensamblados a los que se hace referencia. En resumen, requiere bastante contexto para saber lo que significa.

Es cierto que en la gran mayoría de los casos Stringy stringse unirá al mismo tipo. Pero usar Stringtodavía significa que los desarrolladores están dejando su programa para interpretación en lugares donde solo hay una respuesta correcta. Cuando se Stringune al tipo incorrecto, puede dejar a los desarrolladores depurando durante horas, archivando errores en el equipo del compilador y, en general, perdiendo el tiempo que podría haberse ahorrado mediante el uso string.

Otra forma de visualizar la diferencia es con esta muestra:

string s1 = 42; // Errors 100% of the time  
String s2 = 42; // Might error, might not, depends on the code

Muchos argumentarán que, si bien esta información es técnicamente precisa, el uso Stringtodavía está bien porque es extremadamente raro que una base de código defina un tipo de este nombre. O que cuando Stringse define es una señal de una mala base de código.

[...]

Verá que Stringse define para una serie de propósitos completamente válidos: ayudantes de reflexión, bibliotecas de serialización, lexers, protocolos, etc. Para cualquiera de estas bibliotecas Stringvs. stringtiene consecuencias reales dependiendo de dónde se use el código.

Así que recuerde cuando vea el debate Stringvs. stringesto se trata de semántica, no de estilo. Elegir una cadena le da un significado nítido a su base de código. Elegir Stringno está mal, pero está dejando la puerta abierta para sorpresas en el futuro.

Nota: Copié / pegué la mayor parte de la publicación del blog por razones de archivo. Ignoro algunas partes, por lo que recomiendo omitir y leer la publicación del blog si puedes.

aloisdg
fuente