parametros parameter opcionales c# c#-4.0 optional-parameters

parameter - parametros opcionales c#



¿Cómo puedo predeterminar un parámetro a Guid.Empty en C#? (5)

Solución

Puede usar el new Guid() lugar

public void Problem(Guid optional = new Guid()) { // when called without parameters this will be true var guidIsEmpty = optional == Guid.Empty; }

También puede usar el default(Guid)

default(Guid) también funcionará exactamente como new Guid() .

Debido a que Guid es un tipo de valor, no un tipo de referencia, por lo tanto, el default(Guid) no es igual a null , por el contrario, es igual a llamar al constructor predeterminado.

Lo que significa que esto:

public void Problem(Guid optional = default(Guid)) { // when called without parameters this will be true var guidIsEmpty = optional == Guid.Empty; }

Es exactamente lo mismo que el ejemplo original.

Explicación

¿Por qué Guid.Empty no Guid.Empty ?

La razón por la que recibe el error es porque Empty se define como:

public static readonly Guid Empty;

Por lo tanto, es una variable, no una constante (definida como static readonly no como const ). El compilador solo puede tener valores conocidos del compilador como valores predeterminados de los parámetros del método (no solo conocidos en tiempo de ejecución).

La causa principal es que no se puede tener un const de ninguna struct , a diferencia de enum por ejemplo. Si lo intenta, no se compilará.

La razón una vez más es que struct no es un tipo primitivo.
Para obtener una lista de todos los tipos primitivos en .NET, consulte http://msdn.microsoft.com/en-gb/library/system.typecode.aspx
(tenga en cuenta que enum generalmente hereda int , que es una primitiva)

¡Pero el new Guid() no es una constante también!

No digo que necesite una constante. Necesita algo que pueda decidirse en tiempo de compilación. Empty es un campo, por lo tanto, su valor no se conoce en tiempo de compilación (solo al comienzo del tiempo de ejecución).

El valor del parámetro predeterminado debe conocerse en tiempo de compilación, que puede ser un valor const o algo definido mediante una característica C # que hace que el valor se conozca en tiempo de compilación, como default(Guid) o new Guid() (que se decide en tiempo de compilación para struct s ya que no puede modificar el constructor de la struct en el código).

Si bien puede proporcionar default o new fácilmente, no puede proporcionar un const (porque no es un tipo primitivo o una enum como se explicó anteriormente). Entonces, nuevamente, no digo que el parámetro opcional en sí mismo necesita una constante, sino el valor conocido del compilador.

Deseo decir:

public void Problem(Guid optional = Guid.Empty) { }

Pero el compilador se queja de que Guid.Empty no es una constante de tiempo de compilación.

Como no deseo cambiar la API, no puedo usar:

Nullable<Guid>


El compilador es bastante correcto; Guid.Empty no es una constante en tiempo de compilación. Puedes intentar hacer una sobrecarga de métodos como esta:

public void Problem() { Problem(Guid.Empty); }


La respuesta aceptada no funciona en ASP.NET MVC y causa este error en tiempo de ejecución:

[ArgumentException: The parameters dictionary contains a null entry for parameter ''optional'' of non-nullable type ''System.Guid'' for method ''System.Web.Mvc.ActionResult Problem(System.Guid)'' ....

En cambio, puede hacer lo siguiente:

public void Problem(Guid? optional) { if (optional == null) { optional = new Guid(); } }


No puedes usar:

default ( Guid ) ?


Guid.Empty es equivalente a la new Guid() , que es equivalente a la default(Guid) . Entonces puedes usar:

public void Problem(Guid optional = default(Guid))

o

public void Problem(Guid optional = new Guid())

Tenga en cuenta que el new Foo() valor de new Foo() solo se aplica cuando:

  • Realmente estás llamando al constructor sin parámetros
  • Foo es un tipo de valor

En otras palabras, cuando el compilador sabe que es realmente el valor predeterminado para el tipo :)

(Curiosamente, estoy 99.9% seguro de que no llamará a ningún new Foo() constructor de new Foo() que haya creado. No puede crear dicho constructor en un tipo de valor en C #, pero puede hacerlo en IL.)

Puede usar la opción default(Foo) para cualquier tipo.