.NET面试题系列[4] - C# 基础知识(2)
2016-08-11 17:47
507 查看
2 类型转换
面试出现频率:主要考察装箱和拆箱。对于有笔试题的场合也可能会考一些基本的类型转换是否合法。重要程度:10/10
CLR最重要的特性之一就是类型安全性。在运行时,CLR总是知道一个对象是什么类型。对于基元类型之间的相互转换,可以显式或者隐式执行,例如将一个int转换为long。但如果将精度较大的类型转化为精度较小的类型,必须显式执行,且可能会丢失精度,但不会发生异常。可以利用checked关键字强制掷出OverflowException异常。
CLR允许将一个对象转化为它的任何基类型。C#不要求任何特殊语法即可将一个对象转换为它的任何基类型。然而,将对象转换为它的某个派生类型时,C#要求开发人员只能进行显式转换,因为这样的转换可能在运行时失败。
2.1 基元类型的类型转换
对基元类型进行转换时,可以显式或者隐式执行。如果遇到丢失精度的情况,C#将会向下取整(即无论如何都是舍去)。例如,对int的最大值转换为byte,将会得到255。对一个小数位精度较高的数转化为小数位精度较低的数,则简单的舍去多余的小数位。1 int quantity; 2 if (int.TryParse(txtQuantity.Text, out quantity) == false) 3 { 4 quantity = 0; 5 }
View Code
代码变得十分简单易懂。当然,直接使用显式转换也是一种方法。显式转换和TryParse并没有显著的性能区别。
3.5 字符串的驻留(interning)
从来没有人问过我关于这方面的问题,我也是不久之前才学到的。简单来说,字符串驻留是CLR的JIT做代码优化时,送给我们的一个小礼物。CLR会维护一个字符串驻留池(内部哈希表),并在新建字符串时,探查是否已经有相同值的字符串存在。只有以下两种情况才会自动探查。1. 如果编译器发现已经有相同值的字符串存在,则不新建字符串(在堆上),而是让新旧两字符串变量在栈上指向同一个堆上的字符串值。如果没有则在驻留池中增加一个新的成员。
var s1 = "123"; var s2 = "123"; Console.WriteLine(System.Object.Equals(s1, s2)); //输出 True Console.WriteLine(System.Object.ReferenceEquals(s1, s2)); //输出 True
这意味着,堆上只有一条字符串“123”(隐式驻留)。如果我们预先知道许多字符串对象都可能有相同的值,就可以利用这点来提高性能。字符串的驻留的另一个体现方式是常量字符串相加的优化。下面例子输出结果也是两个True:
string st1 = "123" + "abc"; string st2 = "123abc"; Console.WriteLine(st1 == st2); Console.WriteLine(System.Object.ReferenceEquals(st1, st2));
堆上的字符串只有一个 ----“123abc”。下面例子则稍有不同:
string s1 = "123"; string s2 = s1 + "abc"; string s3 = "123abc"; Console.WriteLine(s2 == s3); Console.WriteLine(System.Object.ReferenceEquals(s2, s3));
第二个布尔值为False,因为变量和常量相加的动作不会被编译器优化。
并非每次新建字符串,或者通过某种方式生成了一条新的字符串时,其都会被驻留。例如,上面例子中,变量字符串和常量字符串相加,就没有触发驻留行为,同理ToString,ToUpper等方法也不会(只有上面两种情况才会)。我们也可以通过访问驻留池来显式留用字符串。我们可以使用方法string.Intern为驻留池新增一个字符串,或者使用方法IsInterned探查字符串是否已经被驻留。
因为变量字符串和常量字符串相加无法利用驻留行为,所以无论我们怎么改进,上面的最后一行总是会输出False。例如:
string s1 = "123"; String.Intern("123abc"); string s2 = s1 + "abc"; string s3 = "123abc"; Console.WriteLine(s2 == s3); Console.WriteLine(System.Object.ReferenceEquals(s2, s3));
此时s2的创建根本不会搭理驻留池。同理,这样也不行:
string s1 = "123"; String.Intern("123"); string s2 = 123.ToString(); Console.WriteLine(System.Object.ReferenceEquals(s2, s1));
通常来说,字符串驻留只有在常量字符串的分配和相加时才有意义。而且,我们要注意到字符串驻留的一个负面影响:驻留池的内存不受GC管辖,所以要到程序结束才会释放。
相关文章推荐
- .NET面试题系列[5] - 垃圾回收:概念与策略
- 轻松搞定二叉树面试题
- 求职系列1--树构造、遍历
- 安卓基础面试一
- Java Web 初级程序员 -第6天学习内容:this,final,instance of
- 面试常考算法题
- java 面试可能所需的问题
- 程序员的七种武器
- Java面试宝典——Java基础部分(一)
- Java Web 初级程序员 -第6天学习内容:类封装
- android面试(基础篇 10)
- .NET面试题系列[8] - 泛型
- Java Web 初级程序员 -第6天学习内容:类方法
- 2016校招内推 -- 阿里巴巴前端 -- 四面面试经历
- Java开发岗位面试题归类
- 一名3年工作经验的程序员应该具备的技能
- Java开发岗位面试题归类---怎么好好的准备面试,也算是发展学习方向
- 逃离伪PHP程序员应该做的事
- java面试总结
- 最全面的java和Android面试题