studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones .net string design

.net - para - manual de programacion android pdf



¿Por qué está String.Format estático? (22)

Comparar

String.Format("Hello {0}", "World");

con

"Hello {0}".Format("World");

¿Por qué los diseñadores de .Net eligieron un método estático sobre un método de instancia? ¿Qué piensas?


.NET Strings son inmutables
Por lo tanto, tener un método de instancia no tiene ningún sentido.

Según esa lógica, la clase de cadena no debería tener métodos de instancia que devuelvan copias modificadas del objeto, pero tiene mucho (Trim, ToUpper, etc.). Además, muchos otros objetos en el marco también lo hacen.

Estoy de acuerdo en que si lo convirtieran en un método de instancia, Format parece que sería un nombre incorrecto, pero eso no significa que la funcionalidad no deba ser un método de instancia.

¿Por qué no esto? Es consistente con el resto del framework .NET

"Hello {0}".ToString("Orion");


Porque el método Format no tiene nada que ver con el valor actual de una cadena.

Eso es cierto para todos los métodos de cadena porque las cadenas .NET son inmutables.

Si no fuera estático, necesitarías una cadena para comenzar.

Lo hace: la cadena de formato.

Creo que este es solo otro ejemplo de los muchos fallos de diseño en la plataforma .NET (y no me refiero a esto como una llama, todavía encuentro que el framework .NET es superior a la mayoría de los otros frameworks).


@Jared:

Los métodos estáticos no sobrecargados y no heredados (como Class.b (a, c)) que toman una instancia como la primera variable son semánticamente equivalentes a una llamada a método (como ab (c))

No, no lo son.

(Suponiendo que compila al mismo CIL, lo cual debería)

Ese es tu error. El CIL producido es diferente. La diferencia es que los métodos miembro no pueden invocarse en valores null , por lo que el CIL inserta una verificación contra valores null . Obviamente, esto no se hace en la variante estática.

Sin embargo, String.Format no permite valores null , por lo que los desarrolladores tuvieron que insertar una verificación manualmente. Desde este punto de vista, la variante de método miembro sería técnicamente superior.


Bueno, supongo que debes ser bastante particular al respecto, pero como dice la gente, tiene más sentido que String.Format sea estático debido a la semántica implícita. Considerar:

"Hello {0}".Format("World"); // this makes it sound like Format *modifies* // the string, which is not possible as // strings are immutable. string[] parts = "Hello World".Split('' ''); // this however sounds right, // because it implies that you // split an existing string into // two *new* strings.


Creo que es porque Format no toma una cadena per se, sino una "cadena de formato". La mayoría de las cadenas son iguales a cosas como "Bob Smith" o "1010 Main St" o lo que es lo mismo que "Hola {0}", generalmente solo ingresas esas cadenas de formato cuando estás tratando de usar una plantilla para crear otra cadena, como un método de fábrica, y por lo tanto se presta a un método estático.


Creo que es porque es un método de creación (no estoy seguro de si hay un mejor nombre). Todo lo que hace es tomar lo que le das y devolver un solo objeto de cadena. No opera en un objeto existente. Si no fuera estático, necesitarías una cadena para comenzar.


Creo que se ve mejor en general usar String.Format, pero podría ver un punto en querer tener una función no estática para cuando ya tienes una cadena almacenada en una variable que deseas "formatear".

Como un lado, todas las funciones de la clase de cadena no actúan en la cadena, sino que devuelven un nuevo objeto de cadena, porque las cadenas son inmutables.


En realidad, no sé la respuesta, pero sospecho que tiene algo que ver con el aspecto de invocar métodos directamente en los literales de cadenas.

Si recuerdo correctamente (en realidad no lo verifiqué porque no tengo un IDE antiguo a mano), las primeras versiones de C # IDE tenían problemas para detectar llamadas de método contra literales de cadenas en IntelliSense, y eso tiene un gran impacto en la detectabilidad de la API. Si ese fuera el caso, escribir lo siguiente no le daría ninguna ayuda:

"{0}".Format(12);

Si fue forzado a escribir

new String("{0}").Format(12);

Sería claro que no había ninguna ventaja para hacer que el método Format fuera un método de instancia en lugar de un método estático.

Las bibliotecas .NET fueron diseñadas por muchas de las mismas personas que nos dieron MFC, y la clase String en particular tiene un gran parecido con la clase CString en MFC. MFC tiene un método de formato de instancia (que usa códigos de formato de estilo de impresión en lugar del estilo de llaves rizadas de .NET), lo cual es doloroso porque no existe un literal de CString. Entonces, en una base de código de MFC en la que trabajé, veo mucho de esto:

CString csTemp = ""; csTemp.Format("Some string: %s", szFoo);

que es doloroso (No estoy diciendo que el código anterior sea una excelente manera de hacer cosas incluso en MFC, pero parece ser la forma en que la mayoría de los desarrolladores del proyecto aprendieron a usar CString :: Format). Viniendo de ese legado, puedo imaginarme que los diseñadores de API intentaban evitar ese tipo de situación nuevamente.


Esto es para evitar confusiones con los métodos .ToString() .

Por ejemplo:

double test = 1.54d; //string.Format pattern string.Format("This is a test: {0:F1}", test ); //ToString pattern "This is a test: " + test.ToString("F1");

Si Format era un método de instancia en una cadena, esto podría causar confusión, ya que los patrones son diferentes.

String.Format () es un método de utilidad para convertir varios objetos en una cadena formateada.

Un método de instancia en una cadena hace algo con esa cadena.

Por supuesto, podrías hacer:

public static string FormatInsert( this string input, params object[] args) { return string.Format( input, args ); } "Hello {0}, I have {1} things.".FormatInsert( "world", 3);


Lo primero que hice cuando tuve que actualizar a VS2008 y C # 3, fue hacer esto

public static string F( this string format, params object[] args ) { return String.Format(format, args); }

Entonces ahora puedo cambiar mi código de

String.Format("Hello {0}", Name);

a

"Hello {0}".F(Name);

que preferí en ese momento. Hoy en día (2014) no me molesto porque no es más que otra molestia volver a agregar eso a cada proyecto aleatorio que creo, o vincularlo en alguna biblioteca de bolsa de utilidades.

¿En cuanto a por qué los diseñadores de .NET lo eligieron? Quién sabe. Parece completamente subjetivo. Mi dinero está en cualquiera

  • Copiando Java
  • Al tipo que lo escribió en ese momento subjetivamente le gustó más.

No hay realmente otras razones válidas que pueda encontrar


Los métodos de instancia son buenos cuando tienes un objeto que mantiene algún estado; el proceso de formatear una cadena no afecta la cadena en la que está operando (léase: no modifica su estado), crea una nueva cadena.

Con los métodos de extensión, ahora puede tener su torta y comerla también (es decir, puede usar la última sintaxis si le ayuda a dormir mejor por la noche).


Los métodos estáticos no sobrecargados y no heredados (como Class.b (a, c)) que toman una instancia como la primera variable son semánticamente equivalentes a una llamada a método (como ab (c)), por lo que el equipo de la plataforma hizo un arbitrario, elección estética. (Suponiendo que compila al mismo CIL, lo que debería hacer). La única forma de saberlo sería preguntarles por qué.

Posiblemente lo hicieron para mantener las dos cadenas cerca de la otra lexigraphically, es decir,

String.Format("Foo {0}", "Bar");

en lugar de

"Foo {0}".Format("bar");

Desea saber a qué se asignan los índices; quizás pensaron que la parte ".Format" simplemente agrega ruido en el medio.

Curiosamente, el método ToString (al menos para los números) es el opuesto: number.ToString ("000") con la cadena de formato en el lado derecho.


No sé por qué lo hicieron, pero en realidad ya no importa:

public static class StringExtension { public static string FormatWith(this string format, params object[] args) { return String.Format(format, args); } } public class SomeClass { public string SomeMethod(string name) { return "Hello, {0}".FormatWith(name); } }

Eso fluye mucho más fácil, en mi humilde opinión.


No veo nada de malo en que sea estático ...

La semántica del método estático parece tener mucho más sentido para mí. Tal vez es porque es un primitivo. Cuando los primitivos se utilizan con frecuencia, se debe hacer que el código de utilidad para trabajar con ellos sea lo más claro posible. Además, creo que la semántica es mucho mejor con String.Formato que con "MyString BLAH BLAH {0}". Formato . ..


Otra razón para String.Format es la similitud con la función printf de C. Se suponía que permitía a los desarrolladores de C tener más facilidad para cambiar de idioma.


Porque el método Format no tiene nada que ver con el valor actual de una cadena. El valor de la cadena no se usa. Toma una cadena y devuelve uno.



Todavía no lo he probado, pero podrías hacer un método de extensión para lo que quieras. No lo haría, pero creo que funcionaría.

También encuentro que String.Format() más en línea con otros métodos estáticos modelados como Int32.Parse() , long.TryParse() , etc.

También puedes utilizar un StringBuilder nube si quieres un formato no estático. StringBuilder.AppendFormat()


Un gran objetivo de diseño para C # era hacer que la transición de C / C ++ a ella sea lo más fácil posible. El uso de la sintaxis de punto en un literal de cadena sería muy extraño para alguien con solo un fondo C / C ++, y el formateo de cadenas es algo que un desarrollador probablemente haga el primer día con el lenguaje. Así que creo que hicieron que sea estático hacerlo más cercano al territorio familiar.


String.Format toma al menos una Cadena y devuelve una Cadena diferente. No es necesario modificar la cadena de formato para devolver otra cadena, por lo que tiene poco sentido hacer eso (ignorando el formateo de la misma). Por otro lado, no sería tan String.Format hacer que String.Format sea ​​una función miembro, excepto que no creo que C # permita las funciones miembro de const como C ++. [Por favor corrígeme y esta publicación si lo hace.]


.NET Strings son inmutables

Por lo tanto, tener un método de instancia no tiene ningún sentido.

String foo = new String(); foo.Format("test {0}",1); // Makes it look like foo should be modified by the Format method. string newFoo = String.Format(foo, 1); // Indicates that a new string will be returned, and foo will be unaltered.


String.Format tiene que ser un método estático porque las cadenas son inmutables. Convertirlo en un método de instancia implicaría que podría usarlo para "formatear" o modificar el valor de una cadena existente. Esto no se puede hacer, y convertirlo en un método de instancia que devolvió una nueva cadena no tendría sentido. Por lo tanto, es un método estático.