zoukankan      html  css  js  c++  java
  • .NET框架:为什么我们要尽量使用框架内建的功能,“.NET研究”而不是重新发明 狼人:

      有很多人经常会持有这样的疑问:为什么 .NET 框架要把一些很简单的功能也封装起来上海企业网站制作?而有些人所坚持的“有现成的就用现成的”的习惯在那些“明明只是很简单的功能却被封装了起来”的情况下也显得很可笑。那么,实际上到底有没有必要用那些本来就很简单的封装?这些简单的封装到底具有什么样的意义呢?

      其实大部分这样的简单的封装都是针对“跨平台使用”而设计的。有些人可能会说:.NET 框架有什么跨平台可言?其实 .NET 框架虽然现在只提供 Windows 上的版本,但其它平台上的 CLI 实现,如 Mono、DotGNU 等等也都有赖于 .NET 框架和 CLI 的预见性方能成为现实;而可以在多种环境中使用的 RIA 平台 Silverlight 也是将这种思想发挥到了极致。

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

      有的人看到这里可能会想:包了两层方法性能多差啊,用到它的地方自己写位移运算不是也可以么?不要这样做。实际上,CLR 的 JIT 编译功能会把简单的方法进行内联编译,所以像是 NetworkToHostOrder 这样的方法在进行 JIT 编译之后结果和直接使用位移运算并没有区别,而在这里偏执地直接使用位移运算,不仅性能没有实质上的提升,还会导致代码难以维护;而且这样的代码如果到了使用 Big-Endian 字节序上海闵行企业网站设计与制作的计算上海徐汇企业网站设计与制作机上,就不能用了!

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

      与此相似的,还有:有些具有 Visual Basic 5/6 编程经验的人在使用 Win32API 的时候会习惯使用 Long 或者 Int32 来当作各种 Handle 的等价类型,然而这样做是错的!如果你去查看 SDK 中关于 HANDLE 的定义,你会发现:

    typedef PVOID HANDLE;

      也就是说,实际上在 64 位程序里,Handle 和指针一样,是 64 位的——虽然绝大部分情况下这 64 位的 Handle 只有低 32 位有效,但是数据类型本身需要的 64 位空间不能忽视。所以实际上在需要用到任何类型的 Handle 的场所,都应该使用 IntPtr,而非 Visual Basic 中的 Long 或者 CLR 中的 Int32,这样才能保证代码在 IA-64、x86-64 硬件平台上正常运行。

      而最为有用,又最为复杂,以致于很多人不愿意去了解的,则是关于“低锁定技术”的各种封装。例如,ReaderWriterLock(Slim)、Lazy<T>、ConcurrentDictionary<TKey, TValue>等等。由于这些封装的内部实现实在是很复杂,不管是从篇幅上考虑还是从笔者我的能力上去考虑,想详细、深入地去解释实在是不现实,所以这里只能介绍一下大致上的原理了。

      低锁定技术是一种由来已久的设计方式,有兴趣的人可以在网络上自行搜索相关的资料。低锁定技术的大致思路就是:对于没有初始化的值,在第一次读取的时候需要锁定并将之初始化;一经初始化之后,进行读取时不需要任何锁定操作。

    不过尽管低锁定看上去是个很聪明的做法,可实际实现起来却要考虑很多问题,因此也有很多文章警告过,不要尝试实现低锁定,因为实际上是会产生意外的。

    实际上 CPU 可能会按照一定的模式来优化内存操作,改变某些读、写操作的顺序;又或者是因为读取了已经缓存的数据而导致了判断失误,致使同一时间尝试进行访问的其它线程读取到了错误的数据,结果采用低锁定技术的程序却发生了异常。

    关于这个问题,想要了解细节的同学可以参考这些文章:http://msdn.microsoft.com/en-us/magazine/cc163715.aspxhttp://www.ibm.com/developerworks/cn/java/j-dcl.htm上海徐汇企业网站制作l、http://msdn.microsoft.com/en-us/library/ff650316.上海企业网站设计与制作aspx、http://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 框架会为你解决好那些恼人的跨平台兼容性问题。

  • 相关阅读:
    Android游戏开发22:Android动画的实现J2me游戏类库用于Android开发
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第三部分,完整代码)
    使用OGR创建dxf格式矢量数据
    mysql 数据库引擎 MyISAM InnoDB 大比拼 区别
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第二部分)
    mysql 更改数据库引擎
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第一部分)
    android 数字键盘使用
    MySQL Innodb数据库性能实践
    eclipse : Error while performing database login with the driver null
  • 原文地址:https://www.cnblogs.com/waw/p/2216991.html
Copyright © 2011-2022 走看看