Paramètre par défaut pour CancellationToken


96

J'ai du code asynchrone auquel je voudrais ajouter un CancellationToken. Cependant, il existe de nombreuses implémentations où cela n'est pas nécessaire, je voudrais donc avoir un paramètre par défaut - peut-être CancellationToken.None. cependant,

Task<x> DoStuff(...., CancellationToken ct = null)

rendements

Une valeur de type «» ne peut pas être utilisée comme paramètre par défaut car il n'y a pas de conversion standard pour le type «System.Threading.CancellationToken»

et

Task<x> DoStuff(...., CancellationToken ct = CancellationToken.None)

La valeur du paramètre par défaut pour «ct» doit être une constante de compilation

Existe-t-il un moyen d'avoir une valeur par défaut pour CancellationToken?

Réponses:


151

Il s'avère que ce qui suit fonctionne:

Task<x> DoStuff(...., CancellationToken ct = default(CancellationToken))

qui, selon la documentation , est interprété de la même manière que CancellationToken.None:

Vous pouvez également utiliser l' default(CancellationToken)instruction C # pour créer un jeton d'annulation vide.


4
C'est exactement ce que fait actuellement le framework en interne, mais je ne le ferais pas dans mon code. Pensez à ce qui se passe avec votre code si Microsoft modifie son implémentation et CancellationToken.Nonedevient quelque chose de plus que default(CancellationToken).
noseratio

10
@Noseratio Cela briserait considérablement la rétrocompatibilité, donc je ne m'attendais pas à ce que cela se produise. Et que ferait default(CancellationToken)- on d'autre ?
svick

3
@Noseratio: Vous êtes trop rigide. Les chances sont CancellationToken.Nonedevenues obsolètes de facto. Même Microsoft utilise à la default(CancellationToken)place. Par exemple, consultez ces résultats de recherche à partir du code source de Entity Framework.
drowa

21
De la propriété MSDN CancellationToken.None : «Vous pouvez également utiliser l'instruction C # default (CancellationToken) pour créer un jeton d'annulation vide» . Aucun n'est une erreur jusqu'à ce qu'une future version de C # l'accepte comme paramètre par défaut.
MuiBienCarlota

5
Idem ici Pour compenser les deux combinaisons intermédiaires manquantes, les développeurs peuvent transmettre None ou un CancellationToken par défaut pour le paramètre cancelToken et null pour le paramètre progress.
Arek Bal

25

Existe-t-il un moyen d'avoir une valeur par défaut pour CancellationToken?

Malheureusement, cela n'est pas possible, car ce CancellationToken.Nonen'est pas une constante de temps de compilation, qui est une exigence pour les valeurs par défaut dans les arguments facultatifs.

Vous pouvez cependant fournir le même effet en créant une méthode surchargée au lieu d'essayer d'utiliser les paramètres par défaut:

Task<x> DoStuff(...., CancellationToken ct)
{
    //...
}

Task<x> DoStuff(....)
{
    return DoStuff(...., CancellationToken.None);
}

6
Il s'agit de la méthode recommandée pour gérer cela, comme expliqué dans la documentation du modèle asynchrone basé sur les tâches sur MSDN (en particulier dans la section Choix des surcharges à fournir ).
Sam Harwell

CancellationToken.None == default true
eoleary

5
Quel est le problème CancellationToken cancellationToken = default(CancellationToken)? Également décrit ici blogs.msdn.microsoft.com/andrewarnottms/2014/03/19/…
Ray

20

Voici plusieurs solutions, par ordre décroissant de bonté générale:

1. En utilisant default(CancellationToken)comme valeur par défaut:

Task DoAsync(CancellationToken ct = default(CancellationToken)) {  }

Sémantiquement, CancellationToken.Noneserait le candidat idéal pour la valeur par défaut, mais ne peut pas être utilisé en tant que tel car ce n'est pas une constante de compilation. default(CancellationToken)est la prochaine meilleure chose car il s'agit d'une constante de compilation et officiellement documentée comme équivalente àCancellationToken.None .

2. Fournir une surcharge de méthode sans CancellationTokenparamètre:

Ou, si vous préférez les surcharges de méthode aux paramètres facultatifs (voir ceci et cette question sur ce sujet):

Task DoAsync(CancellationToken ct) {  } // actual method always requires a token
Task DoAsync() => DoAsync(CancellationToken.None); // overload producing a default token

Pour les méthodes d'interface, la même chose peut être obtenue en utilisant des méthodes d'extension:

interface IFoo
{
    Task DoAsync(CancellationToken ct);
}

static class Foo
{
    public static Task DoAsync(this IFoo foo) => foo.DoAsync(CancellationToken.None);
}

Cela se traduit par une interface plus mince et évite aux implémenteurs d'écrire explicitement la surcharge de la méthode de transfert.

3. Rendre le paramètre nullable et utiliser nullcomme valeur par défaut:

Task DoAsync(…, CancellationToken? ct = null)
{
     ct ?? CancellationToken.None 
}

J'aime moins cette solution parce que les types Nullable sont livrés avec une petite surcharge d'exécution, et les références au jeton d'annulation deviennent plus verbeuses en raison de l'opérateur de fusion null ??.


11

Une autre option consiste à utiliser un Nullable<CancellationToken>paramètre, à le définir par défaut nullet à le gérer dans la méthode:

Task<x> DoStuff(...., CancellationToken? ct = null) {
    var token = ct ?? CancellationToken.None;
    ...
}

brillant! de loin, c'est la meilleure réponse
John Henckel

4

Les versions plus récentes de C # permettent une syntaxe simplifiée pour la version par défaut (CancellationToken). Par exemple:

Task<x> DoStuff(...., CancellationToken ct = default)

-1

La réponse de Tofutim est à sens unique, mais d'après les commentaires, je vois que les gens ont des problèmes avec cela.

Dans ce cas, j'ai suggéré que l'on puisse avoir une méthode comme suit:

Task<x> DoStuff(...., CancellationToken ct)
{
} 

et surchargez-le comme:

Task<x> DoStuff(....)
{
    return DoStuff(...., CancellationToken.None);
}

Cela compile, car la valeur de CancellationToken.Nonen'est pas requise au moment de la compilation.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.