web-dev-qa-db-fra.com

Comment puis-je définir par défaut un paramètre sur Guid.Empty en C #?

Je souhaite dire:

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

Mais le compilateur se plaint que Guid.Empty n'est pas une constante de temps de compilation.

Comme je ne souhaite pas modifier l’API, je ne peux pas utiliser:

 Nullable<Guid>
167
Ian Ringrose

Solution

Vous pouvez utiliser new Guid() à la place

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

Vous pouvez également utiliser default(Guid)

default(Guid) fonctionnera également exactement comme new Guid().

Comme Guid est un type de valeur et non de type référence, default(Guid) n'est pas égal à null par exemple, il équivaut à appeler le constructeur par défaut.

Ce qui signifie que ceci:

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

C'est exactement la même chose que l'exemple original.

Explication

Pourquoi Guid.Empty N'a-t-il pas fonctionné?

La raison pour laquelle vous obtenez l'erreur est parce que Empty est défini comme suit:

public static readonly Guid Empty;

Il s’agit donc d’une variable et non d’une constante (définie comme static readonly Et non de const). Le compilateur ne peut avoir que des valeurs connues du compilateur en tant que valeurs par défaut des paramètres de méthode (non connues à l'exécution).

La cause fondamentale est que vous ne pouvez pas avoir un const de n'importe quel struct, contrairement à enum par exemple. Si vous l'essayez, il ne sera pas compilé.

La raison encore une fois est que struct n'est pas un type primitif.
Pour obtenir la liste de tous les types primitifs dans .NET, voir http://msdn.Microsoft.com/en-gb/library/system.typecode.aspx
(notez que enum hérite généralement de int, qui est une primitive)

Mais new Guid() n'est pas une constante aussi!

Je ne dis pas qu'il a besoin d'une constante. Il faut quelque chose qui puisse être décidé en temps de compilation. Empty est un champ, sa valeur n'est donc pas connue au moment de la compilation (uniquement au tout début de son exécution).

La valeur du paramètre par défaut doit être connue au moment de la compilation, ce qui peut être une valeur const, ou un élément défini à l'aide d'une fonctionnalité C # qui permet de connaître la valeur au moment de la compilation, comme default(Guid) ou new Guid() (décidé lors de la compilation pour structs car vous ne pouvez pas modifier le constructeur struct dans le code).

Bien que vous puissiez fournir default ou new facilement, vous ne pouvez pas fournir un const (car ce n'est pas un type primitif ou un enum comme expliqué ci-dessus). Donc, encore une fois, ne pas dire que le paramètre optionnel lui-même a besoin d’une constante, mais d’une valeur connue du compilateur.

210
Meligy

Guid.Empty Équivaut à new Guid(), ce qui équivaut à default(Guid). Pour que vous puissiez utiliser:

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

ou

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

Notez que la valeur new Foo() est niquement applicable lorsque:

  • Vous appelez vraiment le constructeur sans paramètre
  • Foo est un type de valeur

En d'autres termes, quand le compilateur sait que c'est vraiment la valeur par défaut pour le type :)

(Fait intéressant, je suis sûr à 99,9% que cela ne sera pas appeler n'importe quel constructeur personnalisé new Foo() que vous auriez créé. Vous ne pouvez pas créer un tel constructeur dans un type de valeur en C # , mais vous pouvez le faire en IL.)

Vous pouvez utiliser l'option default(Foo) pour le type any.

148
Jon Skeet

Ne pouvez-vous pas utiliser:

default ( Guid ) ?

17
Nick

La réponse acceptée ne fonctionne pas dans ASP.NET MVC et provoque cette erreur d'exécution:

[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)' ....

Au lieu de cela, vous pouvez effectuer les opérations suivantes:

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

Le compilateur est tout à fait correct; Guid.Empty n'est pas une constante de compilation. Vous pouvez essayer de créer une surcharge de méthode comme ceci:

public void Problem()
{
    Problem(Guid.Empty);
}
4
a CVn