C#特性-CallerMemberName、CallerFilePath和CallerLineNumber的介绍和应用

介绍

在csharp中,CallerMemberName, CallerFilePath, 和 CallerLineNumber 是编译时常量,它们是csharp 5.0引入的特性,用于提供有关调用堆栈的信息,通常用于日志记录和调试。这些特性可以自动填充方法的参数,无需显式传递信息。

所属命名空间:

System.Runtime.CompilerServices

所属程序集:

System.Runtime.dll

CallerMemberName

定义

CallerMemberNameAttribute 类

允许获取方法调用方的方法或属性名称。

csharp 复制代码
[System.AttributeUsage(System.AttributeTargets.Parameter, Inherited=false)]
public sealed class CallerFilePathAttribute : Attribute

作用

CallerMemberName 提供调用方成员的名称(方法或属性)。

使用效果

调用位置 CallerMemberName获取的成员名称结果
方法、属性或事件 方法,属性或事件的名称
构造函数 字符串 ".ctor"
静态构造函数 字符串 ".cctor"
析构函数 该字符串 "Finalize"
用户定义的运算符或转换 生成的名称成员,例如, "op_Addition"。
特性构造函数 特性所应用的成员的名称

使用示例

定义一个方法加上一个默认参数,增加CallerMemberName特性

csharp 复制代码
 public void Work([CallerMemberName] string memberName = "")
 {
     Console.WriteLine("CallerMemberName:" + memberName);
 }

在方法中调用:

csharp 复制代码
   void Playing()
   {
       Work();
   }

在构造函数中调用:

csharp 复制代码
     internal class Program
     {
         static void Main(string[] args)
         {
             Console.WriteLine("Hello, World!");
             TestClass testClass = new TestClass();
             // testClass.Playing();
    
             Console.ReadKey();
         }
     }
     
    class TestClass
    {
        public TestClass()
        {
            Work();
        }

        public void Playing()
        {
            Work();
        }

        public void Work([CallerMemberName] string memberName = "")
        {
            Console.WriteLine("CallerMemberName:" + memberName);
        }
    }

CallerFilePath

定义

CallerFilePathAttribute 类

允许获取包含调用方的源文件的完整路径。 这是编译时的文件路径。

csharp 复制代码
[System.AttributeUsage(System.AttributeTargets.Parameter, Inherited=false)]
public sealed class CallerFilePathAttribute : Attribute

作用

CallerFilePath 提供调用者的源文件路径。

使用示例:

定义一个方法加上一个默认参数,增加CallerFilePath 特性,调用时,会自动返回调用文件的完整路径

csharp 复制代码
  class TestClass
  {
      public void Playing()
      {
          Work();
      }

      public void Work([CallerFilePath] string filePath = "")
      {
          Console.WriteLine("CallerFilePath:" + filePath);
      }
  }

CallerLineNumber

定义

CallerLineNumberAttribute 类

允许获取源文件中调用方法的行号。

csharp 复制代码
[System.AttributeUsage(System.AttributeTargets.Parameter, Inherited=false)]
public sealed class CallerLineNumberAttribute : Attribute

作用

CallerLineNumber 提供调用者的源文件中的行号。

使用场景

CallerMemberNameCallerFilePathCallerLineNumber几个特性必须用于具有默认值的可选参数。 必须为可选参数指定显式默认值。 不能将特性用于未指定为可选的参数。

1.MVVM模式

在绑定数据时实现 INotifyPropertyChanged 接口。 此接口允许对象的属性通知绑定控件该属性已更改,以便此控件能够显示更新的信息。 如果没有 CallerMemberName 特性,则必须将属性名称指定为文本。

csharp 复制代码
public class ViewModelBase : INotifyPropertyChanged
  {
      public event PropertyChangedEventHandler PropertyChanged;

      public void OnPropertyChanged([CallerMemberName]string propertyName = "")
      {
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
  }
  
  

如果不加[CallerMemberName],每次调用OnPropertyChanged时,都要加上对应属性

加了[CallerMemberName],只需要直接调用OnPropertyChanged();无需再一一传参数。

csharp 复制代码
 public class MainWindowViewModel : ViewModelBase
 {
     private string _name;
     private string _mySelectedItem;
     private string _status;

     public string Name
     {
         get
         {
             return _name;
         }
         set
         {
             _name = value;
             OnPropertyChanged();
         }
     }

     public string MySelectedItem
     {
         get
         {
             return _mySelectedItem;
         }
         set
         {
             _mySelectedItem = value;
             OnPropertyChanged();
         }
     }

     public string Status
     {
         get
         {
             return _status;
         }
         set
         {
             _status = value;
             OnPropertyChanged();
         }
     }

}

2.日志

在日志记录中包含调用该方法的信息,用于调试和调用记录,创建一个打印日志的方法,加上上面这些标签,然后只要在需要打印的地方调用,即可打印,使用时把`。

csharp 复制代码
       public void Log(
           string message,
           [CallerMemberName] string memberName = "",
           [CallerFilePath] string sourceFilePath = "",
           [CallerLineNumber] int sourceLineNumber = 0
       )
       {
           //打印日志
           Console.WriteLine("------------------------");
           Console.WriteLine("Message:" + message);
           Console.WriteLine("MemberName:" + memberName);
           Console.WriteLine("FilePath:" + sourceFilePath);
           Console.WriteLine("LineNumber:" + sourceLineNumber);
           Console.WriteLine("------------------------");
       }

完整代码示例:

csharp 复制代码
    internal class Program
    {
        static void Main(string[] args)
        {
            TestClass testClass = new TestClass();
            testClass.Log("主函数执行开始");
            Console.WriteLine("Hello, World!");
            testClass.Playing();
            testClass.Log("主函数执行结束");
            Console.ReadKey();
        }
    }

    class TestClass
    {
        public void Playing()
        {
            Log("执行play");
        }

        public void Log(
            string message,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "",
            [CallerLineNumber] int sourceLineNumber = 0
        )
        {
            //打印日志
            Console.WriteLine("------------------------");
            Console.WriteLine("Message:" + message);
            Console.WriteLine("MemberName:" + memberName);
            Console.WriteLine("FilePath:" + sourceFilePath);
            Console.WriteLine("LineNumber:" + sourceLineNumber);
            Console.WriteLine("------------------------");
        }
    }

效果:

相关推荐
懒大王爱吃狼26 分钟前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
秃头佛爷1 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
待磨的钝刨1 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
△曉風殘月〆3 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
XiaoLeisj3 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师4 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
逐·風4 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq5 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端