增强型 C# 属性语法的提案






3.07/5 (11投票s)
2003年8月19日
3分钟阅读

69110

2
提案使 C# 属性更加灵活,同时保留智能字段语法。
引言
Microsoft .NET 平台为软件程序员提供了 VB、C# 等一系列非常强大的语言,并且还在不断发展。这些语言的代码编写语法在某种程度上非常相似,因为它们都使用 Microsoft CLR(公共语言运行时),这是 .NET 平台的核心。大多数现代面向对象 (OO) 语言都支持基本类型、类、方法、运算符、异常处理、线程、事件处理和程序流程控制。在处理 C# 时,我认为语言的某些功能可以以略有不同的方式实现,以提供更大的灵活性。
本文是系列文章的第一篇,将建议对 .NET 语言中上述一些功能领域进行增强。本文中的示例使用 C# 语言语法编写,并假定读者已熟悉该语法。
什么是 CLR 属性?
CLR 使用新的语法来定义类的属性。CLR 属性是类型的一个成员,它指定一个或两个对应于命名值的方法。这种语法使属性看起来就像是该类中的一个字段(也称为智能字段)。该语法是字段和方法语法的混合体,或者是属性是逻辑字段和物理方法的交叉。
CLR 属性的结构如图所示。属性最多包含两个访问器方法(get/set)及其关联的类型。PropertyInfo 类提供对属性元数据的访问,并发现属性的属性。它通过调用 GetAccessors()(返回 set 和 get 方法的 MethodInfo 对象)、GetGetMethod()(返回 get 方法的 MethodInfo 对象)或 GetSetMethod()(返回 set 方法的 MethodInfo 对象)方法来访问其底层方法。PropertyType 属性(无双关之意)返回属性的类型。
// Current Permissible C# Property Syntax
public class Foo
{
private string name;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
}
上述属性语法会导致生成两个带有 specialname 元数据属性的方法,该属性会通知编译器和工具(例如 IntelliSense)隐藏属性的单个方法,以供正常使用。如果您想知道,这正是属性不能使用 ref 或 out 关键字传递给方法的原因,而如果您使用字段,则可以。
public string get_Name() // The getter.
public void set_Name(string value) // The setter.
分析问题
为了实现更好的封装,我们经常需要为属性的 getter 和 setter 设置不同的访问范围。通常,getter 被分配 public 范围,而 setter 可以应用较低的 protected 范围。这使得 setter 只对子类可见,并防止任何外部模块或应用程序通过公共属性 setter 来更改我们对象的状态。问题:当前的 CLS(公共语言规范)只允许我们为类中声明的每个属性设置一个访问限定符。为属性的 getter 和 setter 分配不同的访问修饰符会导致编译错误。请考虑下面列出的类 Foo 的修改代码。
public class Foo
{
private string name;
public string Name
{
get { return this.name; }
}
// Compiler Error! The class 'Foo' already contains a definition for 'Name'.
protected string Name
{
set { this.name = value; }
}
}
解决方法:除了一个 protected 方法(用于设置属性的值)外,还定义一个公共的只读属性。这否定了使属性看起来像智能字段的前提。
private string name;
// Current C# property syntax. Public getter for name.
public string Name
{
get { return this.name; }
}
// Protected SetName method definition.
protected void SetName(string name)
{
this.name = name;
}
// Somewhere else in the code, access the property of object type foo
Foo foo = new Foo();
string name = foo.Name; // Ok
foo.SetName("myName"); // Not intuitive anymore.
提案:属性的定义语法如下所示。每个属性最多允许有一个 getter 和 setter,无论其访问范围如何。这种新语法还允许程序员单独为 getter/setter 或两者都使用 virtual 关键字。
// The desired syntax Public getter and protected setter.
virtual public string Name
{
get { return this.name; }
}
// Protected setter access. Should compile Ok as only one setter is defined
protected string Name
{
set { this.name = value; }
}
上述属性语法将导致生成两个方法,与之前一样,但对访问和 virtual 限定符进行了适当修改。
virtual public string get_Name()
// The getter. Notice the virtual keyword and public access modifier.
protected void set_Name(string value)
// The setter. Notice the protected access modifier.
使用新的拟议语法编写的以下代码应导致编译器错误,因为每个属性只允许一个 getter 和 setter。
public string Name
{
get { return this.name; }
set { this.name = value; }
}
// Error Duplicate definition of the Name setter
protected string Name
{
set { this.name = value; }
}
// OR
public string Name
{
get { return this.name; }
set { this.name = value; }
}
// Error Duplicate definition of the Name setter
protected string Name
{
get { return this.name; }
}
我希望 C# 属性在未来会变得更加友好,如果 C# 社区能够注意到的话。在那之前,祝大家 .NET 愉快……
参考/链接
Essential .NET Volume 1 (The Common Language Runtime) - Don Box and Chris Sells.Inside C# - Tom Archer.
Microsoft Visual C# .NET Step By Step - John Sharp, Jon Jagger.
Alternative Simplified C# Property Syntax (Proposal) - Scott Zimmerman 在 C# Corner 上的文章。