web-dev-qa-db-fra.com

Quel est le ?[]? syntaxe en C #?

Pendant que j'étudiais le délégué qui est en fait une classe abstraite dans - Delegate.cs , j'ai vu la méthode suivante dans laquelle je ne comprends pas

  • Pourquoi la valeur de retour utilise ? bien qu'il s'agisse déjà d'un type de référence ( classe )
  • ?[]? signification sur le paramètre

Pourriez-vous expliquer?

public static Delegate? Combine(params Delegate?[]? delegates)
{
    if (delegates == null || delegates.Length == 0)
        return null;

    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}
85
snr

Explication étape par étape:

params Delegate?[] delegates - C'est un tableau de nullable Delegate

params Delegate?[]? delegates - Le tableau entier peut être nul

Étant donné que chaque paramètre est du type Delegate? et vous retournez un index du Delegate?[]? tableau, il est donc logique que le type de retour soit Delegate? sinon le compilateur retournerait une erreur comme si vous étiez en train de reprendre et int d'une méthode qui retourne une chaîne.

Vous pouvez par exemple changer votre code pour renvoyer un type Delegate comme ceci:

public static Delegate Combine(params Delegate?[]? delegates)
{
    Delegate defaulDelegate = // someDelegate here
    if (delegates == null || delegates.Length == 0)
        return defaulDelegate;

    Delegate d = delegates[0] ?? defaulDelegate;
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}
66
Athanasios Kataras

Types de référence nullables sont nouveaux dans C # 8.0, ils n'existaient pas auparavant.

C'est une question de documentation et de la façon dont les avertissements sont générés au moment de la compilation.

L'exception "objet non défini sur une instance d'un objet" est une exception courante et silencieuse. Mais il s'agit d'une exception d'exécution, elle peut déjà être partiellement découverte au moment de la compilation.

Pour un réglementé Delegate d vous pouvez toujours appeler

 d.Invoke();

ce qui signifie, vous pouvez le coder, au moment de la compilation, rien ne se passera. Il peut soulever des exceptions lors de l'exécution.

Alors que pour un nouveau Delegate? p ce Code

 p.Invoke();

produira un avertissement du compilateur. CS8602: Dereference of a possibly null reference sauf si vous écrivez:

 p?.Invoke();

ce qui signifie, appelez uniquement s'il n'est pas nul.

Donc, vous documentez une variable peut contenir null ou non. Il déclenche des avertissements plus tôt et peut éviter plusieurs tests pour null. Le même que ce que vous avez pour int et int?. Vous savez avec certitude, l'un n'est pas nul - et vous savez comment convertir l'un en l'autre.

25
Holger

En C # 8, il faut explicitement marquer les types de référence comme nullables.

Par défaut, ces types ne peuvent pas contenir null, un peu comme les types de valeur. Bien que cela ne change pas la façon dont les choses fonctionnent sous le capot, le vérificateur de type vous demandera de le faire manuellement.

Le code donné est refactorisé pour fonctionner avec C # 8, mais il ne bénéficie pas de cette nouvelle fonctionnalité.

public static Delegate? Combine(params Delegate?[]? delegates)
{
    // ...[]? delegates - is not null-safe, so check for null and emptiness
    if (delegates == null || delegates.Length == 0)
        return null;

    // Delegate? d - is not null-safe too
    Delegate? d = delegates[0];
    for (int i = 1; i < delegates.Length; i++)
        d = Combine(d, delegates[i]);

    return d;
}

Voici un exemple de code mis à jour (ne fonctionnant pas, juste une idée) exploitant cette fonctionnalité. Cela nous a sauvé d'un contrôle nul et a un peu simplifié cette méthode.

public static Delegate? Combine(params Delegate[] delegates)
{
    // `...[] delegates` - is null-safe, so just check if array is empty
    if (delegates.Length == 0) return null;

    // `d` - is null-safe too, since we know for sure `delegates` is both not null and not empty
    Delegate d = delegates[0];

    for (int i = 1; i < delegates.Length; i++)
        // then here is a problem if `Combine` returns nullable
        // probably, we can add some null-checks here OR mark `d` as nullable
        d = Combine(d, delegates[i]);

    return d;
}
5
amankkg