Fastställa uppringarens information med hjälp av attribut som tolkas av C#-kompilatorn

Med hjälp av informationsattribut får du information om anroparen till en metod. Du hämtar filsökvägen för källkoden, radnumret i källkoden och namnet på anroparen. Om du vill hämta information om medlemssamtal använder du attribut som tillämpas på valfria parametrar. Varje valfri parameter anger ett standardvärde. I följande tabell visas de anroparinformationsattribut som definieras i System.Runtime.CompilerServices namnområdet:

Attribut beskrivning Typ
CallerFilePathAttribute Fullständig sökväg till källfilen som innehåller anroparen. Den fullständiga sökvägen är sökvägen vid kompileringstiden. String
CallerLineNumberAttribute Radnummer i källfilen som metoden anropas från. Integer
CallerMemberNameAttribute Anroparens metodnamn eller egenskapsnamn. String
CallerArgumentExpressionAttribute Strängrepresentation av argumentuttrycket. String

Den här informationen hjälper dig att spåra och felsöka och hjälper dig att skapa diagnostikverktyg. I följande exempel visas hur du använder informationsattribut för anropare. Vid varje anrop till TraceMessage metoden infogas anroparinformationen för argumenten till de valfria parametrarna.

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

Du anger ett explicit standardvärde för varje valfri parameter. Du kan inte använda anroparinformationsattribut för parametrar som inte har angetts som valfria. Anroparinformationsattributen gör inte en parameter valfri. I stället påverkar de standardvärdet som skickas när argumentet utelämnas. Värden för uppringarens information genereras som literaler i det mellanliggande språket (IL) vid kompileringstillfället. Till skillnad från resultatet av StackTrace egenskapen för undantag påverkas inte resultatet av fördunkling. Du kan uttryckligen ange valfria argument för att styra uppringarens information eller dölja uppringarens information.

Medlemsnamn

Du kan använda CallerMemberName attributet för att undvika att ange medlemsnamnet som ett String argument för den anropade metoden. Med den här tekniken undviker du problemet att Byt namn på refaktorisering inte ändrar String värdena. Den här fördelen är särskilt användbar för följande uppgifter:

  • Använda spårnings- och diagnostikrutiner.
  • Implementera gränssnittet vid bindning av INotifyPropertyChanged data. Med det här gränssnittet kan egenskapen för ett objekt meddela en bunden kontroll om att egenskapen har ändrats. Kontrollen kan visa den uppdaterade informationen. CallerMemberName Utan attributet måste du ange egenskapsnamnet som en literal.

I följande diagram visas de medlemsnamn som returneras när du använder attributet CallerMemberName .

Anrop sker inom Resultat av medlemsnamn
Metod, egenskap eller händelse Namnet på den metod, egenskap eller händelse som anropet kommer från.
Konstruktor Strängen ".ctor"
Statisk konstruktor Strängen ".cctor"
Finalizer Strängen "Slutför"
Användardefinierade operatorer eller konverteringar Det genererade namnet på medlemmen, till exempel "op_Addition".
Attributkonstruktor Namnet på den metod eller egenskap som attributet tillämpas på. Om attributet är ett element inom en medlem (till exempel en parameter, ett returvärde eller en allmän typparameter) är det här resultatet namnet på den medlem som är associerad med det elementet.
Ingen medlem som innehåller (till exempel sammansättningsnivå eller attribut som tillämpas på typer) Standardvärdet för den valfria parametern.

Argumentuttryck

Du använder System.Runtime.CompilerServices.CallerArgumentExpressionAttribute när du vill att uttrycket ska skickas som ett argument. Diagnostikbibliotek kanske vill ge mer information om de uttryck som skickas till argumenten. Genom att ange det uttryck som utlöste diagnostiken har utvecklare, förutom parameternamnet, mer information om villkoret som utlöste diagnostiken. Den extra informationen gör det lättare att åtgärda.

I följande exempel visas hur du kan ange detaljerad information om argumentet när det är ogiltigt:

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

Du anropar den enligt följande exempel:

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

Uttrycket som används för condition matas in av kompilatorn i message argumentet. När en utvecklare anropar Operation med ett null argument lagras följande meddelande i ArgumentException:

Argument failed validation: <func is not null>

Med det här attributet kan du skriva diagnostikverktyg som ger mer information. Utvecklare kan snabbare förstå vilka ändringar som behövs. Du kan också använda CallerArgumentExpressionAttribute för att avgöra vilket uttryck som användes som mottagare för tilläggsmetoder. Följande metod tar ett exempel på en sekvens med jämna mellanrum. Om sekvensen har färre element än frekvensen rapporterar den ett fel:

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

I föregående exempel används operatorn nameof för parametern sequence. Den funktionen är tillgänglig i C# 11. Innan C# 11 måste du ange namnet på parametern som en sträng. Du kan anropa den här metoden på följande sätt:

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

Föregående exempel skulle utlösa en ArgumentException vars meddelande är följande text:

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

Se även