如前一节所述,RegKeyAttribute属性构造器为:
public RegKeyAttribute(RegHives Hive, String ValueName)
根据这个属性构造器原型,我们把这个属性附着给一个字段:
[RegKey(RegHives.HKEY_CURRENT_USER, "Foo")]
public int Foo;
其实可以使编程更加容易。如果参数在大多数情况下不变,可以使用位置参数(positional parameter)和命名参数(named parameter)设置默认值。
位置参数是必须的,前面例子中的Hive和ValueName都是位置参数。
而命名过的参数实际上不是在属性构造器中定义的。相反,它们是非静态的字段和特性(Property,这本书把这个词翻译成特性,可能为了和现在在讲的Attribute区分吧,但我总觉得别扭
)。因此,命名过的参数使客户能够在属性被实例化时设置属性的字段和特性(Property),而不必为客户可能设置的字段和特性,而不必为客户可能设置的字段和特性每种组合创建一个构造器。
在规定了位置参数之后,用户可以使用FieldOrPropertyName = Value语法引用字段或特性。我们修改RegKeyAttribute属性演示这个过程。
//[RegKey(RegHives.HKEY_CURRENT_USER, "Foo")]
[RegKey("Foo")]
public int Foo;
在这个修改中,ValueName是唯一的位置参数。Hive变成了可选的命名参数。
那么又“如何定义命名过的参数呢?”因为只有位置参数被包含在构造器的定义中(故是必须的),所以只需将这个参数从构造器中删除。(我理解这里说的“这个参数”应该是指Hive吧)。这样,用户就可以将字段或者特性作为命名过的参数引用,条件是这些字段不是readonly,static,const的,这些特性必须包含设置方法而且不是静态的。
现在,用户可以以两种方式之一附着这个属性。一种是:
//either
[RegKey(“Foo“)]
public int Foo;
输出为:
Foo will be saved in HKEY_CLASS_ROOT \\ Foo
另一种方式为:
//or
[RegKey(“Foo“, Hive = RegHives.HKEY_LOCAL_MACHINE)]
public int Foo;
输出为:
Foo will be saved in HKEY_LOCAL_MACHINE \\ Foo
这样安排为字段提供了默认值,也可以在需要时覆盖默认值。
但是RegKeyAttribute.Hive的默认值又从何而来呢?
其实由于RegKeyAttribute.Hive是一个枚举值,底层类型是int,是一种值类型,根据定义,编译器将他初始化为0!
可是如果某些原因你不愿意以0作为默认值,那么唯一的方法,修改代码使0值是无效的。
public enum RegHives
{
HKEY_CLASS_ROOT = 1,
HKEY_CURRENT_USER,
HKEY_LOCAL_MACHINE,
HKEY_CURRENT_CONFIG
}
(经过我的实验,这时候的输出是
Foo will be saved in 0 \\ Foo
)
现在我们知道,RegKeyAttribute.Hive成为0的惟一原因是编译器将它初始化为0,而且用户没有通过命名参数覆盖这个值。现在可以使用以下代码初始化这个值:
public RegKeyAttribute(String ValueName)
{
if(this.Hive == 0)
this.Hive = RegHives.HKEY_CURRENT_USER;
this.ValueName = ValueName;
}
PS:
虽然大多数原文是书上的,但我也尽量以我自己的理解提炼,当然自己的话还是放在括号里,虽然打得有点累的,但是这样一边理解,一边打,效果还挺好的,呵呵,因为昨天看这一节看得晕乎晕乎的,今天写了一下blog清楚多了。
属性参数 - 位置参数和命名参数
最新推荐文章于 2023-03-28 13:51:29 发布