深入理解C#类型系统

这是我参与 11 月更文挑战的第 26 天,活动详情查看:2021 最后一次更文挑战

前言

C#描述成强类型的语言是一种静态类型的语言。

类型系统被分为强/弱、安全/不安全、静态/动态等 。C# 1的类型系统是静态的、显式的和安全的。直到C# 4引入了动态类型。

在某些“强类型”定义中,要求禁止任何形式的转换(不管是显式还是隐式转换),这明显会使C#失去资格。 但在另一些定义中,却相当接近(甚至等同于)静态类型,这会使C#获得资格。

静态类型和动态类型

C#是静态类型的:每个变量都有一个特定的类型,而且该类型在编译时是已知的。

object o = "hello";
Console.WriteLine(((string)o).Length);
复制代码

静态类型? 

静态这个词用来描述表达式的编译时类型,因为它们使用不变的(unchanging)数据来分析哪些操作可用。假设某个变量声明为Stream类型,那么不管变量的值为MemoryStream还是FileStream,甚至不是流类型(包括空引用),它的类型都不会发生改变。

然而静态类型系统中也可以有一些动态行为,如虚方法调用所执行的实际实现依赖于所调用的对象。尽管这种“不变信息”的理念也是static修饰符的背后动机,但简便起见还是应该认为静态成员属于类型本身,而不属于某个类型的特定实例。

动态类型

动态类型的实质是变量中含有值,但那些值并不限于特定的类型,所以编译器不能执行相同形式的检查。相反,执行环境试图采取一种合适的方式来理解引用值的给定表达式。

显式类型和隐式类型

显式类型和隐式类型的区别只有在静态类型的语言中才有意义。

  • 对于显式类型来说,每个变量的类型都必须在声明中显式指明。

  • 隐式类型则允许编译器根据变量的用途来推断变量的类型。

值类型和引用类型

类(使用class来声明)是引用类型,而结构(使用struct来声明)是值类型。特殊情况包括如下方面:

  • 数组类型是引用类型,即使元素类型是值类型(所以即便int是值类型,int[]仍是引用类型);
  • 枚举(使用enum来声明)是值类型;
  • 委托类型(使用delegate来声明)是引用类型;
  • 接口类型(使用interface来声明)是引用类型,但可由值类型实现。

殊表达式的值是什么?

  • 值类型的表达式,它的值就是表达式的值
  • 引用类型的表达式,它的值是一个引用,而不是该引用所指代的对象。 表达式String.Empty的值不是一个空字符串——而是对空字符串的一个引用。

变量的值在它声明时的位置存储。

  • 局部变量的值总是存储在栈(stack)中,实例变量的值总是存储在实例本身存储的地方。 这个结论只有在C# 1中完全成立。以后会讲到,在更高版本C#中,在特定情况下,局部变量最终可能存储在堆中。

  • 引用类型实例(对象)总是存储在堆(heap)中,静态变量也是。

猜你喜欢

转载自juejin.im/post/7034908101878743047