A hívó adatainak meghatározása a C# fordító által értelmezett attribútumok használatával

Az infoattribútumok használatával információt kaphat a hívóról egy metódushoz. Lekérheti a forráskód fájl elérési útját, a forráskód sorszámát és a hívó tagnevét. A taghívó adatainak lekéréséhez használja az opcionális paraméterekre alkalmazott attribútumokat. Minden választható paraméter egy alapértelmezett értéket ad meg.

A C# nyelv referenciadokumentuma a C# nyelv legújabb kiadású verzióját ismerteti. Emellett a közelgő nyelvi kiadás nyilvános előzetes verziójú funkcióinak kezdeti dokumentációját is tartalmazza.

A dokumentáció azonosítja azokat a funkciókat, amelyeket először a nyelv utolsó három verziójában vagy az aktuális nyilvános előzetes verziókban vezetnek be.

Jótanács

Ha meg szeretné tudni, hogy mikor jelent meg először egy funkció a C#-ban, tekintse meg a C# nyelvi verzióelőzményeiről szóló cikket.

Az alábbi táblázat a névtérben System.Runtime.CompilerServices definiált hívóinformációs attribútumokat sorolja fel:

Jellemző Leírás Típus
CallerFilePathAttribute A hívót tartalmazó forrásfájl teljes elérési útja. A teljes elérési út a fordítási időpontban megadott elérési út. String
CallerLineNumberAttribute Annak a forrásfájlnak a sorszáma, amelyből a metódust meghívják. Integer
CallerMemberNameAttribute A hívó metódusneve vagy tulajdonságneve. String
CallerArgumentExpressionAttribute Az argumentumkifejezés sztring-ábrázolása. String

Ezek az információk segítenek a nyomkövetésben és a hibakeresésben, és segítenek diagnosztikai eszközök létrehozásában. Az alábbi példa bemutatja, hogyan használhat hívóinformációs attribútumokat. A metódus minden egyes hívása TraceMessage esetén a rendszer beszúrja a hívó adatait az opcionális paraméterek argumentumaihoz.

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

Minden választható paraméterhez explicit alapértelmezett értéket kell megadnia. Nem alkalmazhat hívóinformációs attribútumokat olyan paraméterekre, amelyek nem választhatók. A hívó információattribútumai nem teszik kötelezővé a paramétert. Ehelyett az argumentum kihagyásakor átadott alapértelmezett értéket befolyásolják. A fordító a fordításkor literálként bocsát ki hívóinformációs értékeket a köztes nyelvbe (IL). A kivételek tulajdonságának eredményeitől eltérően az StackTrace obfuscation nem befolyásolja az eredményeket. Explicit módon megadhatja az opcionális argumentumokat a hívó információinak szabályozásához vagy a hívó adatainak elrejtéséhez.

Tagnevek

CallerMemberName Az attribútum használatával elkerülheti, hogy a tag nevét argumentumként String adja meg a hívott metódushoz. Ezzel a technikával elkerülheti azt a problémát, hogy a refactoring keretében történő átnevezés nem módosítja az String értékeket. Ez az előny különösen hasznos a következő feladatokhoz:

  • Nyomkövetési és diagnosztikai rutinok használata.
  • Az interfész implementálása adatok hozzárendelésekor INotifyPropertyChanged. Ez a felület lehetővé teszi, hogy egy objektum tulajdonsága értesítse a kötött vezérlőt a tulajdonság módosításáról. A vezérlő megjelenítheti a frissített információkat. Az CallerMemberName attribútum nélkül a tulajdonság nevét literálként kell megadnia.

Az alábbi diagram az attribútum használatakor CallerMemberName visszaadott tagneveket mutatja.

A hívások a Felhasználói név eredménye
Metódus, tulajdonság vagy esemény Annak a metódusnak, tulajdonságnak vagy eseménynek a neve, amelyből a hívás származik.
Konstruktor A '.ctor' karakterlánc
Statikus konstruktor A ".cctor" sztring
Finalizer "Véglegesítés" karakterlánc
Felhasználó által definiált operátorok vagy konverziók A tag generált neve, például "op_Addition".
Attribútumkonstruktor Annak a metódusnak vagy tulajdonságnak a neve, amelyre az attribútumot alkalmazza. Ha az attribútum egy tag bármely eleme (például paraméter, visszatérési érték vagy általános típusparaméter), ez az eredmény az adott elemhez társított tag neve.
Nem tartalmaz tagot (például szerelvényszintű vagy típusokra alkalmazott attribútumokat) Az opcionális paraméter alapértelmezett értéke.

Argumentumkifejezések

Használja azt a System.Runtime.CompilerServices.CallerArgumentExpressionAttribute kifejezést, amikor argumentumként szeretné átadni a kifejezést. A diagnosztikai kódtárak további részleteket is megadhatnak az argumentumoknak átadott kifejezésekről . A diagnosztika kiváltó kifejezésének megadásával a paraméternév mellett a fejlesztők további részleteket is megtudhatnak a diagnosztika kiváltó feltételéről. Ez a további információ megkönnyíti a javítást.

Az alábbi példa bemutatja, hogyan adhat meg részletes információkat az argumentumról, ha érvénytelen:

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

Az alábbi példában látható módon hívhatja meg:

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

A fordító beszúrja az argumentumban conditionmessage használt kifejezést. Amikor egy fejlesztő argumentummal Operation hívnull, a rendszer a következő üzenetet tárolja a ArgumentExceptionkövetkező helyen:

Argument failed validation: <func is not null>

Ezzel az attribútummal olyan diagnosztikai segédprogramokat írhat, amelyek további részleteket nyújtanak. A fejlesztők gyorsabban megérthetik, hogy milyen módosításokra van szükség. A bővítménytagok fogadójaként használt kifejezés meghatározására is használható CallerArgumentExpressionAttribute . Az alábbi módszer rendszeres időközönként mintát vesz egy sorozatból. Ha a sorozat kevesebb elemből áll, mint a gyakoriság, hibát jelez:

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;
        }
    }
}

Az előző példa az operátort nameof használja a paraméterhez sequence. Ezt a metódust a következőképpen hívhatja meg:

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

Az előző példa egy ArgumentException olyan üzenetet jelenít meg, amelynek üzenete a következő:

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

Lásd még