您的位置:首页 > 其它

.NET框架:为什么我们要尽量使用框架内建的功能,而不是重新发明

2011-01-05 15:08 686 查看
有很多人经常会持有这样的疑问:为什么 .NET 框架要把一些很简单的功能也封装起来?

而有些人所坚持的“有现成的就用现成的”的习惯在那些“明明只是很简单的功能却被封装了起来”的情况下也显得很可笑。

那么,实际上到底有没有必要用那些本来就很简单的封装?这些简单的封装到底具有什么样的意义呢?

其实大部分这样的简单的封装都是针对“跨平台使用”而设计的。

有些人可能会说:.NET 框架有什么跨平台可言?

其实 .NET 框架虽然现在只提供 Windows 上的版本,但其它平台上的 CLI 实现,如 Mono、DotGNU 等等也都有赖于 .NET 框架和 CLI 的预见性方能成为现实;而可以在多种环境中使用的 RIA 平台 Silverlight 也是将这种思想发挥到了极致。

举个例子来说,.NET 框架中 IPAddress 类型具有 NetworkToHostOrder 和 HostToNetworkOrder 方法,如果你使用 Reflector 来查看反编译后的代码,你会发现 NetworkToHostOrder 只是调用了 HostToNetworkOrder,而 HostToNetworkOrder 的原理也只不过是一些简单的位移运算而已。

有的人看到这里可能会想:包了两层方法性能多差啊,用到它的地方自己写位移运算不是也可以么?

不要这样做。

实际上,CLR 的 JIT 编译功能会把简单的方法进行内联编译,所以像是 NetworkToHostOrder 这样的方法在进行 JIT 编译之后结果和直接使用位移运算并没有区别,而在这里偏执地直接使用位移运算,不仅性能没有实质上的提升,还会导致代码难以维护;而且这样的代码如果到了使用 Big-Endian 字节序的计算机上,就不能用了!

当然了,如果你善于使用预编译指令之类的工具,这种问题也自然难不倒你。

与此相似的,还有:

有些具有 Visual Basic 5/6 编程经验的人在使用 Win32API 的时候会习惯使用 Long 或者 Int32 来当作各种 Handle 的等价类型,然而这样做是错的!

如果你去查看 SDK 中关于 HANDLE 的定义,你会发现:

http://msdn.microsoft.com/en-us/magazine/cc163715.aspx、http://www.ibm.com/developerworks/cn/java/j-dcl.htmlhttp://msdn.microsoft.com/en-us/library/ff650316.aspxhttp://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html。

尽管这样的问题也可以通过精密的设计而解决,但如果你使用过 C/C++ 并且知道 MemoryBarrier 的概念,你也可以发现下面这些东西:

#ifdef _AMD64_
#define MemoryBarrier __faststorefence
#endif

#ifdef _IA64_
#define MemoryBarrier __mf
#endif

// x86

FORCEINLINE
VOID
MemoryBarrier (
VOID
)
{
LONG Barrier;
__asm {
xchg Barrier, eax
}
}


这也说明在不同的平台上,由内存模型或其它技术细节上的差异所导致的问题,具体的解决办法也是各不相同的。

而对于我们一般的应用程序开发人员来说,要想全面掌握这些解决办法,并且在每个必要的场合准确无误地采取合适的办法也是相当困难的。

其实这样繁琐的问题本来就不应该让一般应用程序开发人员去面对,而是应该让 .NET 框架之类的靠近底层的设施去解决。

所以对于使用 C/C++ 的开发人员来说,当他们用到 MemoryBarrier 的时候,并不需要真的根据目标平台而写入实际的操作代码,只需要插入相应的 MACRO 就可以了。

而实际上,.NET 框架也把这一部分隐藏了起来,在 MSDN 博客上有博文解释了在 CLR 中实现了一种正确的内存操作模型(链接:http://blogs.msdn.com/b/cbrumme/archive/2003/05/17/51445.aspx),而且无论哪种平台上的 .NET 框架(或者其等价物)都会保证它们的行为一致;

同时 .NET 框架中提供的诸如 Lazy<T>、ConcurrentDictionary<TKey, TValue> 等类型,也有助于避免由于对内存模型不了解(比方说,你知道使用 lock 时是不是应该同时使用 MemoryBarrier 或者 Volatile 吗?又或者,你知道应该在什么时候使用、什么时候不需要使用吗?),或者一时间的逻辑误区而写出了存在潜在问题、导致程序不稳定的代码的情形发生。

总地来说,除非是对底层的技术细节具有相当高的程度的了解,并且具有极强的信心可以解决任何问题……否则还是“有现成的就用现成的”比较好,因为这样做的话 .NET 框架会为你解决好那些恼人的跨平台兼容性问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐