CallerMemberName 如何从内部工作?

How does CallerMemberName work from inside?

我找不到任何文档或至少无法从内部找到此类属性如何工作的解释。

    [CallerMemberName] 
    [CallerFilePath] 
    [CallerLineNumber]

Documentation I found 仅显示如何使用它。

是否可以创建您自己的 [CallerMemberNameAttribute] 实现或一些自定义 [CallerObjectAttribute]?

这对我来说很有趣,只是为了学习目的和理解背后的代码。

所以仅供学习之用。属性本身对方法本身没有任何作用,但对它的调用方式有影响。

如果编译器必须创建对该方法的调用,他会检查每个参数,如果它具有这些属性之一,如果是,它会将调用者的名称或文件作为参数值传递。它用另一个默认值覆盖默认值。将默认参数放在那里的要求只是让编译器允许您首先省略此参数。

假设您有这样的代码:

   static void Main(string[] args)
    {
        Test();
        Test1();
    }

    public static void Test(string name = "")
    {
        Console.WriteLine(name);
    }

    public static void Test1([CallerMemberName] string name = "")
    {
        Console.WriteLine(name);
    }

生成的代码与

相同
  static void Main(string[] args)
    {
        Test("");
        Test1("Main");
    }

除非您修改编译器本身,否则您无法通过您的编程模拟这一点。如果调用者的编译器找到这个属性,就会放入这个“Main”字符串(或当前编译的文件的名称)。

如果您显式传递参数值,如代码示例的最后一行,默认值和 CallerMemberName 属性都将被忽略。