Partager via


Déterminer les informations de l’appelant à l’aide d’attributs interprétés par le compilateur C#

À l’aide d’attributs d’informations, vous obtenez des informations sur l’appelant à une méthode. Vous obtenez le chemin du fichier du code source, le numéro de ligne dans le code source et le nom du membre de l’appelant. Pour obtenir les informations sur l'appelant membre, vous utilisez des attributs appliqués aux paramètres facultatifs. Chaque paramètre facultatif spécifie une valeur par défaut. Le tableau suivant répertorie les attributs d'information de l'appel définis dans l'espace de noms System.Runtime.CompilerServices :

Caractéristique Descriptif Catégorie
CallerFilePathAttribute Chemin d’accès complet du fichier source qui contient l’appelant. Le chemin complet est le chemin d’accès au moment de la compilation. String
CallerLineNumberAttribute Numéro de ligne dans le fichier source à partir duquel la méthode est appelée. Integer
CallerMemberNameAttribute Nom de la méthode ou nom de propriété de l’appelant. String
CallerArgumentExpressionAttribute Représentation sous forme de chaîne de l’expression d’argument. String

Ces informations vous aident à suivre et déboguer, et vous aident à créer des outils de diagnostic. L’exemple suivant montre comment utiliser des attributs d’informations de l’appelant. Sur chaque appel à la TraceMessage méthode, les informations de l’appelant sont insérées pour les arguments aux paramètres facultatifs.

public void DoProcessing()
{
    TraceMessage("Something happened.");
}

public void TraceMessage(string message,
        [CallerMemberName] string memberName = "",
        [CallerFilePath] string sourceFilePath = "",
        [CallerLineNumber] int sourceLineNumber = 0)
{
    Trace.WriteLine("message: " + message);
    Trace.WriteLine("member name: " + memberName);
    Trace.WriteLine("source file path: " + sourceFilePath);
    Trace.WriteLine("source line number: " + sourceLineNumber);
}

// Sample Output:
//  message: Something happened.
//  member name: DoProcessing
//  source file path: c:\Visual Studio Projects\CallerInfoCS\CallerInfoCS\Form1.cs
//  source line number: 31

Vous spécifiez une valeur par défaut explicite pour chaque paramètre facultatif. Vous ne pouvez pas appliquer d’attributs d’informations d’appelant aux paramètres qui ne sont pas spécifiés comme facultatifs. Les attributs d’informations de l’appelant ne rendent pas un paramètre facultatif. Au lieu de cela, ils affectent la valeur par défaut passée lorsque l’argument est omis. Les valeurs d’informations de l’appelant sont émises en tant que littéraux dans le langage intermédiaire (IL) au moment de la compilation. Contrairement aux résultats de la propriété pour les exceptions, l’obfuscation StackTrace n’affecte pas les résultats. Vous pouvez fournir explicitement les arguments facultatifs pour contrôler les informations de l’appelant ou masquer les informations de l’appelant.

Noms de membres

Vous pouvez utiliser l’attribut CallerMemberName pour éviter de spécifier le nom du membre comme String argument de la méthode appelée. Vous évitez ainsi le problème que la refactorisation de changement de nom ne modifie pas les valeurs String. Cet avantage est particulièrement utile pour les tâches suivantes :

  • Utilisation de routines de suivi et de diagnostic.
  • Implémenter l’interface INotifyPropertyChanged lors de la liaison de données. Cette interface permet à la propriété d’un objet d’avertir un contrôle lié que la propriété a changé. Le contrôle peut afficher les informations mises à jour. Sans l’attribut CallerMemberName , vous devez spécifier le nom de propriété en tant que littéral.

Le graphique suivant montre les noms de membres retournés lorsque vous utilisez l’attribut CallerMemberName .

Les appels se produisent dans Résultat pour le nom du membre
Méthode, propriété ou événement Nom de la méthode, de la propriété ou de l’événement à partir duquel l’appel provient.
Constructeur La chaîne « .ctor »
Constructeur statique La chaîne « .cctor »
Finaliseur La chaîne « finalize »
Opérateurs ou conversions définis par l’utilisateur Nom généré pour le membre, par exemple « op_Addition ».
Constructeur d’attribut Nom de la méthode ou de la propriété à laquelle l’attribut est appliqué. Si l’attribut est un élément au sein d’un membre (tel qu’un paramètre, une valeur de retour ou un paramètre de type générique), ce résultat est le nom du membre associé à cet élément.
Aucun membre contenant (par exemple, niveau assembly ou attributs qui sont appliqués aux types) Valeur par défaut du paramètre facultatif.

Expressions d’argument

Vous utilisez le System.Runtime.CompilerServices.CallerArgumentExpressionAttribute moment où vous souhaitez que l’expression passe en tant qu’argument. Les bibliothèques de diagnostics peuvent fournir plus de détails sur les expressions passées aux arguments. En fournissant l’expression qui a déclenché le diagnostic, en plus du nom du paramètre, les développeurs ont plus de détails sur la condition qui a déclenché le diagnostic. Ces informations supplémentaires facilitent la correction.

L’exemple suivant montre comment fournir des informations détaillées sur l’argument lorsqu’il n’est pas valide :

public static void ValidateArgument(string parameterName, bool condition, [CallerArgumentExpression("condition")] string? message=null)
{
    if (!condition)
    {
        throw new ArgumentException($"Argument failed validation: <{message}>", parameterName);
    }
}

Vous l’appelez comme indiqué dans l’exemple suivant :

public void Operation(Action func)
{
    Utilities.ValidateArgument(nameof(func), func is not null);
    func();
}

Le compilateur injecte l’expression utilisée dans condition l’argument message . Lorsqu’un développeur appelle Operation avec un null argument, le message suivant est stocké dans les ArgumentExceptionéléments suivants :

Argument failed validation: <func is not null>

Cet attribut vous permet d’écrire des utilitaires de diagnostic qui fournissent plus de détails. Les développeurs peuvent comprendre plus rapidement les modifications nécessaires. Vous pouvez également utiliser la CallerArgumentExpressionAttribute méthode pour déterminer quelle expression a été utilisée comme récepteur pour les membres de l’extension. La méthode suivante échantillonne une séquence à intervalles réguliers. Si la séquence a moins d’éléments que la fréquence, elle signale une erreur :

extension<T>(IEnumerable<T> sequence)
{
    public IEnumerable<T> Sample(int frequency, 
        [CallerArgumentExpression(nameof(sequence))] string? message = null)
    {
        if (sequence.Count() < frequency)
            throw new InvalidOperationException($"Expression doesn't have enough elements: {message}");
        int i = 0;
        foreach (T item in sequence)
        {
            if (i++ % frequency == 0)
                yield return item;
        }
    }
}

L’exemple précédent utilise l’opérateur nameof pour le paramètre sequence. Vous pouvez appeler cette méthode comme suit :

sample = Enumerable.Range(0, 10).Sample(100);

L’exemple précédent lève un ArgumentException message dont le message est le texte suivant :

Expression doesn't have enough elements: Enumerable.Range(0, 10) (Parameter 'sequence')

Voir aussi