《CLR via C#》

前言:本博文记录书中新学到的知识点,值得思考知识点以及一些难点。

第四章 类型基础

4.1所有类型都从System.Object派生

Object.ToString():

默认返回 = this.GetType().FullName

源码标注:

印证:

static void Main(string[] args)
{
    object obj = new object(); 
    Console.WriteLine("ToString:" + obj.ToString() + ",FullName:" + 
                       obj.GetType().FullName);
    Console.ReadLine();
}

结果:

平时输出对象的时候其实就是输出的ToString,对于C#来说,这是VS的功劳。

new与override的不同:

public class TestNew
{
    public string Tea()
    {
        return "茶";
    }
}
public class TestNew1 : TestNew
{
    public new string Tea()
    {
        return "Tea";
    }
}
static void Main(string[] args)
{
    TestNew test = new TestNew1();
    Console.WriteLine(test.Tea());
    Console.ReadLine();
}

输出:

而使用vitrual和override会输出Tea.

第五章 基元类型、引用类型和值类型

5.1 编程语言的基元类型

类似于Int32、Int64,通过源码可知:

32位与64位的int不存在子父类关系,但32位却可以向64位做转换,这得益于编译器的功劳,编译器会自动识别此类转换关系做隐式转换。

对于会产生数据丢失的类型转换,例如Double到Int32,C#总是做向下取整的处理,如(Double)7.9 => (Int32)7.

checked和unchecked基元类型操作

在vs中打开编译器检查溢出:项目->属性->生成->高级->检查运算上溢/下溢。                                                                                                                                                                                                                                                        

  • 使用unchecked操作符,不会检查代码溢出。
    Int32 k = int.MaxValue;
    Int32 l = unchecked(k + 1);
    Console.WriteLine(l);

    结果:

  • 使用checked操作,代码溢出会抛出OverflowException:

值类型的装箱与拆箱(尽可能的在自己的代码中减少装箱的次数)

看看下面的代码会出现几次装箱动作?

public static void Main(string[] args)
{
    Int32 i = 1;
    Object j = i;
    i = 123;
    Console.WriteLine(i + "," + (Int32)j);
}

答案是:3次。开始怎么都没想明白,最后通过书中解释恍然大悟。

首先,Object j = i;很明显,i被装箱一次。

Console.WriteLine(i + "," + (Int32)j),我们来看看它的IL代码:

注意在WriteLine中使用+号编译器会隐式的处理未String.Concat方法,通过编译之后的IL源码也可以看到,有调用Concat的方法,但这里注意我们做的是整型的连接,所以会调用:

所以i会被装箱成arg0,这是第二次装箱。(Int32)j会先拆箱然后装箱,这是第三次装箱。

而装箱操作会影响应用程序性能和增加内存消耗(装箱会在托管堆新建对象),所以提升的做法是降低装箱率,下面是对上述代码的优化:

public static void Main(string[] args)
{
    Int32 i = 1;
    Object j = i;
    i = 123;
    Console.WriteLine(i.ToString() + "," + j);
}

这样之后,便只有Object j = i这一行会装箱了。

还有几种不易被发现的装箱行为:

public static void Main(string[] args)
{
    Int32 i = 1;
    i.GetType();//调用基类方法
    IComparable j = i;//i转型为接口类型
}

IL:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值