zoukankan      html  css  js  c++  java
  • 几个.NET方面的问题——参考答案

    几个.NET方面的问题中,列出了几个.NET方面的问题,但是没有给出问题的答案,因为对于一部分问题我自己也不是很确定。这次只是给出一个参考答案,仅仅作为参考。如有不对的地方,欢迎大家指正。

    1.       为什么要显式地关闭StreamWriter

    这个问题可以从《框架设计》P409找到答案,书上用了专门的一节解释了这个问题。简单来说,因为StreamWriter在调用Write方法向Stream写入数据之后,数据还可能是在StreamWriter的缓冲区中。如果不显式关闭StreamWriter,那么数据能否真正写入Stream中,就要取决于.NETGC先回收Stream还是先回收StreamWriter。如果GC先回收了Stream,那么在回收StreamWriter时,StreamWriter会试图把缓冲区中的数据写入到一个已经关闭的Stream中,从而发生异常。

    2.       如何正确地重写GetHashCode方法?

    这个问题可以从《框架设计》P123找到答案,也是用了专门一节讲述这个问题。一个正确的GetHashCode方法要满足下面的要求:

    1.       Equals方法行为一致。如果a等于b,则aHash应该也等于bHash

    2.       Hash值有良好的分布

    3.       满足生存期的值稳定性。

    4.       最好要快速。

    这么多要求,如果没有写过可能还真一时不好下手,其实只要把与Equals方法相关的字段的Hash值异或起来就可以了。

    3.       C#编译器为什么要用callvirt指令调用实例的非虚方法?

    这个问题也是来源于《框架设计》,作者也很惊讶为什么会这样,不过他只告诉我们这样没有问题,却没有说为什么要这样。P139里的“重要提示”,写到如果一个方法从非虚改成虚方法,如果非虚方法是用call调用,那么这个更改会造成虚方法被非虚地调用,产生不可知的后果。所以干脆都用callvirt好了。

    我看了一下callvirtcall的区别,除了方法调用逻辑有一定不同,callvirt还会检查变量是否为NULL,而call不会。其实call根本就不能检查,它还要调用静态方法呢,检查谁去?而实例方法,一般是要使用实例字段的,这就要求实例不能为null,所以用callvirt顺便检查一下。(其实书中也是想这么解释的,不过书印错了。见下面勘误。)

    所以估计是上面两个原因,让C#团队选择了callvirt。好处多多。

    PS:《框架设计》勘误:P139L3,“call”应该是“callvirt”。

    4.       Struct可以继承吗?为什么?可以有虚方法吗?为什么?

    不可以继承,因为C#语法不允许。(我实在不想这么回答,但是也实在找不出为什么。)

    也不可以有虚方法,都不能继承,虚个屁。

    5.       什么时候用const,什么时候用static readonly

    所有书上都会告诉你const是编译时常量,readonly是运行时常量。

    但是什么时候用呢?比如你想限制你的程序可以运行的实例的个数为5,用哪个好像都可以哦,不过最好用static readonly,因为哪天你可以把这个数改成6。只要你能改的,就用static readonly,而不要用const。什么时候用const?表示MaxInt, PI, e光速等等数学常量,亘古不变的量,才用const。重申一下,个人观点,仅供参考。至于为什么,可以参考这篇文章

    6.       C#为什么要提供析构函数?

    一个原因是为了用于方便地释放本地资源(就是非托管资源)。大家补充。^_^

    7.       有时,程序的Debug Build可以正常运行,而Release Build不能。可能是什么原因?

    我一想到这个问题的时候,感觉无从下手。天知道为什么!谁知道代码怎么写能写出这么恶心的BUG出来。其实细想想,同样的代码,Debug Build可以运行,而Release Build不能运行。只可能是编译器生产的代码不同。只要知道debug buildrelease build有什么不同,这个问题也就解决了。至于总共有多少不同点,可真是不好说。《框架设计》P387专门用了一节讲了一个不同——变量的生存期不同。Debug build为了方便调试,“将所有变量的生存期扩展到方法结束”。而release build中,编译器就不会做这样的事情,这样一个变量就有可能被过早地当作垃圾回收掉了。这就有可能导致debug build可以正常运行,而release build不能。具体解释可以参考《框架设计》。

    这是个开放式的问题,应该不止这一种情况。欢迎大家补充。

     

    另外又想到了几个问题:

    1.       我们都知道短小的方法,有可能在编译时被编译器内联处理。那么在什么情况下,我们会希望阻止一个方法在编译时被内联?

    2.       C#中,有几种方式可以防止一个方法在编译时被内联?

  • 相关阅读:
    React生命周期, 兄弟组件之间通信
    React组件式编程Demo-用户的增删改查
    React之this.refs, 实现数据双向绑定
    CCF CSP 201812-4 数据中心
    CCF CSP 201812-4 数据中心
    PAT 顶级 1020 Delete At Most Two Characters (35 分)
    PAT 顶级 1020 Delete At Most Two Characters (35 分)
    Codeforces 1245C Constanze's Machine
    Codeforces 1245C Constanze's Machine
    CCF CSP 201712-4 行车路线
  • 原文地址:https://www.cnblogs.com/nankezhishi/p/dotnetquestionsa.html
Copyright © 2011-2022 走看看