C#的未来:扩展属性及更多

C#未来系列文章中的下一条提议希望能够使用扩展属性。这一功能是大家期盼已久的特性,但通常来说被认为是不可行的,因为它会带来内存泄露。

\\

实际上,实现扩展属性所需的基础功能在.NET 4.0中就已经具备了。这里的秘密在于,你可以使用某个ConditionalWeakTable类以保存对象与扩展字段之间的映射。其实创建ConditionalWeakTable的目的正是为了提供这种动态类型语言的功能。

\\

Sam Harwell为我们演示了如何正确地使用这个类:

\\
private static readonly ConditionalWeakTable\u0026gt; _extensionField_f;\public static FieldType get_f(T obj)\{\    StrongBox box;\    if (!_extensionField_f.TryGetValue(obj, out box))\        return default(FieldType);\    return box.Value;\}\public static void set_f(T obj, FieldType value)\{\    StrongBox box = _extensionField_f.GetOrCreateValue(obj);\    box.Value = value;\}
\\

扩展类

\\

以上这种方式虽然能够实现最终的目的,但它的语法并不简洁。因此一种被称为“扩展类”的概念就能够派上用场了。可以通过以下语法定义一个扩展类:

\\

public extension class MyClassExtensions : MyClass

\\

在MyClassExtensions中定义的每个方法或属性都会自动成为MyClass中的扩展方法或属性。在MyClassExtensions中定义成员看起来与在MyClass中直接定义成员没有任何差别。这种方式让你能够避免使用旧的语法,即将某个方法定义为静态方法,并在参数中包含一个“this”关键字。

\\

在扩展类中定义的字段和事件将通过上述的ConditionalWeakTable所实现。属性可以明确指定对应的字段或是自动实现,在后一种情况下,其内部实现依然依赖于ConditionalWeakTable的使用。

\\

静态扩展

\\

由于扩展类概念的存在,使得一种被称为“静态扩展方法”的使用方式也成为可能。它允许你为某个类添加一个静态方法,与你为对象添加成员方法的方式相同。

\\

为了澄清这种用法,Erik Schierboom这样写道:

\\
\

比方说,它能够允许我扩展xUnit中的Assert类。

\
\\

思考

\\

虽然这种做法在动态类型语言中很常见,但这种能够为某个类任意添加状态的能力还是让某些开发者感到有些不安。HellBrick总结了人们对于扩展字段的顾虑:

\\
\

看上去对这种功能的尝试是很自然的事,但我担心这个特性可能会很容易遭到误用。如果你想要为某个类的实例附加一个额外的状态,我认为在大部分情况下,更好的方式是继承这个类,或是为它创建一个包装器。无论是哪种做法,你的意图都很明确。使用某种像魔法一样自动附加的弱字段引用,就不清楚它的生命周期,将这种方式作为类的设计方式或许是一种非常廉价的方案,并且具有一定吸引力。但同时,它可能会导致出现一些复杂的代码,增加日后维护的困难。

\
\\

对上述说法的一种反对意见认为,如果没有扩展字段,那么也不可能通过扩展提供自动属性。Chrisaut继续这个讨论:

\\
\

即使扩展字段这条提议通不过,只要属性的setter仍然是允许使用的,就会有开发者尝试着提出自己的解决方案,而其中有半数都存在着一些微秒的错误。比方说,他们可能会创建一个Dictonary\u0026lt;MyClass, string\u0026gt;并保存在属性中。额……这样一来这个实例就永远不会被垃圾回收了,这将带来内存泄露。大多数开发者甚至不知道弱引用和ConditionalWeakTable的存在。

\\

因此如果我们真的要阻止附加额外状态的行为(也就是不希望引入扩展字段),那么我感觉唯一的方法就是明确地表示只允许属性的getter,不支持属性的setter,或者在自动属性中只支持getter。

\\

这样一来大概就可以了。但我猜使用者会试图打破这一限制,我不确定只支持getter是否能够涵盖用户所需的所有场景。或者我们也可以说它已经涵盖了足够多的场景,而剩余的部分不值得实现。

\
\\

扩展字段的另一个问题是对可回收对象的存储。如果你在ConditionalWeakTable中保存了一个可回收(disposable)对象,你需要找到一种方式,在父对象被垃圾回收时显式地回收该对象。ConditionalWeakTable不会自动为你实现这一功能,而依赖于终结器又存在着风险。

\\

查看英文原文:C# Futures: Extension Properties and More

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值