No se puede usar String.Vacío como valor predeterminado para un parámetro opcional


Estoy leyendo C#efectivo por Bill Wagner. En Item 14-Minimize Duplicate Initialization Logic , muestra el siguiente ejemplo de uso de la nueva característica de parámetros opcionales en un constructor:

public MyClass(int initialCount = 0, string name = "")

Observe que usó "" en lugar de string.Empty.
Él comenta:

Notará [en un ejemplo anterior] que el segundo constructor especificó "" para el valor predeterminado en el parámetro name, en lugar del parámetro más habitual string.Empty. Esto se debe a que string.Empty no es una constante en tiempo de compilación. Es una propiedad estática definida en la clase string. Debido a que no es una constante de compilación, no puede usarla para el valor predeterminado de un parámetro.

Si no podemos usar la string.Empty estática en todas las situaciones, entonces ¿eso no derrota el propósito de la misma? Pensé que lo usaríamos para asegurarnos de que tenemos un medio independiente del sistema para referirnos a la cadena vacía. ¿Está mal mi entendimiento? Gracias.

ACTUALIZAR
Solo un comentario de seguimiento. Según MSDN:

Cada parámetro opcional tiene un valor predeterminado como parte de su definición. Si no se envía ningún argumento para ese parámetro, se utiliza el valor predeterminado. Los valores predeterminados deben ser constantes.

Entonces tampoco podemos usar System.Environment.NewLine, o usar objetos recién instanciados como valores predeterminados. No he usado VS2010 todavía, y esto es decepcionante!

Author: Hamid Pourjam, 2010-04-23

9 answers

A partir del compilador de C# 2.0, hay muy poco sentido para String.Empty de todos modos, y de hecho en muchos casos es una pesimización, ya que el compilador puede insertar algunas referencias a "" pero no puede hacer lo mismo con String.Empty.

En C# 1.1 era útil evitar crear muchos objetos independientes que contuvieran la cadena vacía, pero esos días se han ido. "" funciona muy bien.

 55
Author: Andy Mortimer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-23 19:16:55

No hay nada que le impida definir su propia constante para la cadena vacía si realmente desea usarla como un valor de parámetro opcional:

const string String_Empty = "";

public static void PrintString(string s = String_Empty)
{
    Console.WriteLine(s);
}

[Como un aparte, una razón para preferir String.Empty sobre "" en general, que no se ha mencionado en las otras respuestas, es que hay varios caracteres Unicode (ensambladores de ancho cero, etc.) que son efectivamente invisibles a simple vista. Así que algo que se parece a "" no es necesariamente la cadena vacía, mientras que con String.Empty sepa exactamente lo que está usando. Reconozco que esta no es una fuente común de errores, pero es posible.]

 50
Author: Matthew Strawbridge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-25 11:12:46

De la pregunta original:

Pensé que lo usaríamos para asegurarnos de que tenemos un medio independiente del sistema para referirnos a la cadena vacía.

¿De qué manera puede variar la cadena vacía de un sistema a otro? ¡Siempre es una cadena sin caracteres! Estaría realmente asustado si alguna vez encontrara una implementación donde string.Empty == ""devolviera false :) Esto es no lo mismo que algo como Environment.NewLine.

De Counter Terrorist's bounty mensaje:

Quiero Cadena.Empty se puede usar como parámetro predeterminado en la próxima versión de C#. : D

Bueno, eso ciertamente no va a suceder.

Aunque personalmente me hubiera gustado un mecanismo predeterminado muy diferente también, la forma en que funcionan los parámetros opcionales ha estado en. NET desde el principio , y siempre significa incrustar una constante en los metadatos, de modo que el código de llamada pueda copiar esa constante en el sitio de la llamada si no hay un argumento correspondiente proporcionar.

Con string.Empty es realmente inútil - usar "" hará lo que quieras; ¿es que doloroso usar el literal de cadena? (Yo uso el literal en todas partes - nunca uso string.Empty - pero ese es un argumento diferente.)

Eso es lo que me sorprende de esta pregunta - la queja gira en torno a algo que no realmente causa un problema real. Es más importante en los casos en los que desea que el valor predeterminado se calcule en el momento de la ejecución porque podría variar. Por ejemplo, podría imaginar casos en los que desea poder llamar a un método con un parámetro DateTime y tenerlo por defecto en "la hora actual". Por el momento, la única solución vagamente elegante que conozco es:

public void RecordTime(string message, DateTime? dateTime = null)
{
    var realDateTime = dateTime ?? DateTime.UtcNow;
}

... pero eso no siempre es apropiado.

En conclusión:

  • Dudo mucho que esto alguna vez sea parte de C#{[46]]}
  • Para string.Empty es inútil de todos modos
  • Para otros valores que realmente no siempre tenga el mismo valor, realmente puede ser un dolor
 22
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-03 08:55:07

Nunca uso string.Vacío, no le veo el sentido. Tal vez lo hace más fácil para las personas que son realmente nuevas en la programación, pero dudo que sea útil incluso para eso.

 7
Author: Hans Olsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-23 19:13:57

Creo que la idea detrás de string.Vacío es mejora la legibilidad. No es como newline donde hay alguna diferencia entre cómo se representa en diferentes plataformas. Es vergonzoso que no se pueda usar en un parámetro predeterminado. Sin embargo, no causará ningún problema si realiza un puerto entre Windows y algo como Mono en Linux.

 4
Author: Tom Cabanski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-23 19:15:49

Para su información, parece que se impone la misma restricción a los valores pasados a los constructores de atributos: deben ser constantes. Desde string.vacío se define como :

public static readonly string Empty

En lugar de una constante real, no se puede usar.

 3
Author: Shawn Eavis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-27 15:23:47

Si realmente no te gustan los literales de cadena, puedes usar:

public static string MyFunction(string myParam= default(string))
 2
Author: Denise Skidmore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-05 14:23:05

Utilizo string.Empty puramente para la legibilidad.

Si alguien más necesita leer/cambiar mi código más tarde, saben que quería verificar o establecer algo en una cadena vacía. Usar solo "" a veces puede causar errores y confusión porque puede que haya olvidado poner la cadena que quería allí.

Por ejemplo:

if(someString == string.Empty)
{

}

Vs

if(someString == "")
{

}

La primera if declaración me parece mucho más deliberada y legible. Porque esto es sólo una preferencia sin embargo, realmente no veo el tren-smash en tener que usar "" en lugar de string.Empty.

 0
Author: lukejkw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-22 10:52:44

Tal vez la mejor solución a este problema es una sobrecarga de este método, de esta manera:

public static void PrintString() 
{ 
    PrintString(string.Empty);
}
 -1
Author: lokum09,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-26 07:15:58