特性—[CallerMemberName]
Posted kai-liang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了特性—[CallerMemberName]相关的知识,希望对你有一定的参考价值。
[CallerMemberName]
是 C# 中的一个特性(Attribute),用于在方法参数中标记一个字符串参数,用来自动获取调用该方法的成员名称(方法、属性、字段等)。
当在方法参数中使用了 [CallerMemberName]
特性时,如果该参数没有被显式地传入值,编译器会自动将调用方法的成员名称作为参数的默认值。这样,你就无需手动传入成员名称,而是可以直接使用方法的调用者的成员名称。
这个特性通常在实现属性更改通知(Property Change Notification)时非常有用。当你在属性的 setter 方法中调用属性更改通知事件时,可以使用 [CallerMemberName]
来自动获取当前属性的名称,避免手动传入属性名称字符串,减少了硬编码和重复代码。
例如,以下是一个简单的示例,展示了如何使用 [CallerMemberName]
特性:
private string _name; public string Name get return _name; set if (_name != value) _name = value; NotifyPropertyChanged(); // 调用属性更改通知方法 public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
在上述示例中,当 Name
属性的值发生变化时,我们通过调用 NotifyPropertyChanged
方法来触发属性更改通知事件。由于在 NotifyPropertyChanged
方法的参数中使用了 [CallerMemberName]
,所以我们无需手动传入属性名称,编译器会自动将调用 NotifyPropertyChanged
方法的成员名称作为参数的默认值。这样,我们可以在整个类中重复使用该方法,而不必每次都手动传入属性名称。
让我们来详细解释这个例子的代码行:[CallerMemberName] string propertyName = null
[CallerMemberName]
:这是特性的名称,告诉编译器要将该参数设置为调用者的成员名称。string propertyName
:这是参数的声明,指定了参数的类型为字符串,用于存储调用者的成员名称。= null
:这是一个默认值的赋值语句,指定了参数的默认值为null
。这意味着如果在调用NotifyPropertyChanged
方法时未提供参数值,propertyName
参数将自动设置为null
。
所以,当你调用 NotifyPropertyChanged
方法时,如果不传递 propertyName
参数的值,编译器将自动将调用该方法的成员名称赋值给 propertyName
参数。这样,你就可以在方法内部使用该成员名称进行属性更改通知,而无需手动指定属性的名称。
例如,如果在属性的 setter 方法中调用 NotifyPropertyChanged()
,而没有显式传递参数值,propertyName
参数将自动设置为调用该 setter 方法的属性名称。
请注意,[CallerMemberName]
特性只能应用于方法的参数,并且要求参数类型为字符串。它不能应用于其他类型的参数或方法的返回值。
总而言之,[CallerMemberName]
特性提供了一种便捷的方式来获取方法的调用者的成员名称,通常在属性更改通知等场景下使用,减少了手动传入成员名称的工作量,提高了代码的可读性和可维护性。
在实现 INotifyPropertyChanged 时,[CallerMemberName] 与替代方案相比是不是慢?
【中文标题】在实现 INotifyPropertyChanged 时,[CallerMemberName] 与替代方案相比是不是慢?【英文标题】:Is [CallerMemberName] slow compared to alternatives when implementing INotifyPropertyChanged?在实现 INotifyPropertyChanged 时,[CallerMemberName] 与替代方案相比是否慢? 【发布时间】:2014-04-30 02:39:45 【问题描述】:有好文章推荐different ways for implementing INotifyPropertyChanged
。
考虑以下基本实现:
class BasicClass : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void FirePropertyChanged(string propertyName)
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
private int sampleIntField;
public int SampleIntProperty
get return sampleIntField;
set
if (value != sampleIntField)
sampleIntField = value;
FirePropertyChanged("SampleIntProperty"); // ouch ! magic string here
我想用这个替换它:
using System.Runtime.CompilerServices;
class BetterClass : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
// Check the attribute in the following line :
private void FirePropertyChanged([CallerMemberName] string propertyName = null)
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
private int sampleIntField;
public int SampleIntProperty
get return sampleIntField;
set
if (value != sampleIntField)
sampleIntField = value;
// no "magic string" in the following line :
FirePropertyChanged();
但有时我读到[CallerMemberName]
属性与替代品相比性能较差。这是真的吗?为什么?它使用反射吗?
【问题讨论】:
【参考方案1】:不,[CallerMemberName]
的使用并不比上层基本实现慢。
这是因为,根据this MSDN page,
调用者信息值作为文字发送到中间体 编译时的语言 (IL)
我们可以使用任何 IL 反汇编程序(如 ILSpy)检查:该属性的“SET”操作的代码以完全相同的方式编译:
所以这里没有使用反射。
(用VS2013编译的示例)
【讨论】:
同一个链接,但用英语而不是法语:msdn.microsoft.com/en-us/library/hh534540(v=vs.110).aspx @MikedeKlerk 不知道您为什么不直接将其编辑到答案中,尽管我现在已经这样做了。以上是关于特性—[CallerMemberName]的主要内容,如果未能解决你的问题,请参考以下文章
在实现 INotifyPropertyChanged 时,[CallerMemberName] 与替代方案相比是不是慢?