1.CLR
支持的属性有两种:无参属性,这也是我们平常说的属性;有参属性,它在不同的编程语言中有不同的称呼。例如:在C#
中有参属性被称为索引器,而在VB
中被称为默认属性。
2.属性不能作为out
或者ref
参数传给方法,而字段可以。
public class SomeType
{
private static string _name;
private static string Name
{
get { return null; }
set{}
}
static void MethodWithOutParam(out string n) => n = null;
public static void Main()
{
MethodWithOutParam(out Name); // 编译报错
MethodWithOutParam(out _name);
}
}
3.ExpandoObject
配合dynamic
可以动态的插入属性
using System.Dynamic;
dynamic e = new ExpandoObject();
e.x = 6;
e.y = "six";
e.z = DateTime.Now;
// 遍历
foreach (var v in (IDictionary<string,object>)e)
{
Console.WriteLine($"Key={v.Key};Value={v.Value}");
}
// 删除
var d = (IDictionary<string, object>)e;
d.Remove("x");
4.索引器(有参属性)至少要有一个参数,并且这些参数(和返回类型)可以是除void
之外的任意类型。
5.和无参属性的set访问器方法相似,索引器的set访问器方法同样包含了一个隐藏参数,在C#
中称为value
。该参数代表想赋给“被索引元素”的新值。
6.CLR
本身不区分无参属性和有参属性。对CLR
来说,每个属性都只是类型中定义的一对方法和一些元数据。将this[]
作为表达索引器的语法,这纯粹是C#
团队自己的选择。也正是这个选择,所以C#
只允许在对象的实例上定义索引器。C#
不支持定义静态索引器属性,虽然CLR
是支持静态有参属性的。
7.编译器在索引器名称之前附加get_
或者set_
前缀,从而自动生成这些方法的名称。由于C#
的索引器语法不允许开发人员指定索引器名称,所以便指定Item
为默认名称,因此,编译器生成的方法名就是get_Item
和set_Item
。但是可以通过[IndexerNameAttribute]
特性来重命名这些方法。
using System.Runtime.CompilerServices;
[IndexerName("otherName")]
public bool this[int pos]
{
get { } // 这里至少定义一个访问器方法
}
使用该特性标记后,编译器将生成名为get_otherName
和set_otherName
的方法,而不是get_Item
和set_Item
。编译时,C#
编译器会注意到IndexerName
特性,它告诉编译器如何对方法和属性的元数据进行命名。注意,特性本身不会进入程序集的元数据。
System.String
中就是使用了该特性