5.1
基元类型

编译器直接支持的数据类型称为基元类型(primitive type)。

以下4行到吗生成完全相同的IL
            int             a = 0;                  //最方便的语法
            System.Int32    b = 0;                  //方便的语法
            int             c = new int();          //不方便的语法
            System.Int32    d = new System.Int32(); //最不方便的语法 
C#基元类型与对应的FCL类型

C#中的基元类型

FCL类型

是否与CLS兼容

描述

sbyte

System.SByte

N

有符号8位值

byte

System.Byte

Y

无符号8位值

short

System.Int16

Y

有符号16位值

ushort

System.UInt16

N

无符号16位值

int

System.Int32

Y

有符号32位值

uint

System.UInt32

N

无符号32位值

long

System.Int64

Y

有符号64位值

ulong

System.UInt64

N

无符号64位值

char

System.Char

Y

16位Unicode字符(不像非托管C++中那样,char表示的是一个8位值)

float

System.Single

Y

IEEE32位浮点数

double

System.Double

Y

IEEE 64位浮点数

bool

System.Boolean

Y

一个True或者Flase值

decimal

System.Decimal

Y

128位高精度浮点值,通常用于不容许有摄入误差的金融计算场合。在这128位中,1位表示浮点值的符号,96位表示浮点值本身(一个整数值,小数点位置由下面8个位来确定),8位表示用96位值除以浮点值所得结果的10的幂次(0~28)。其余的位尚未使用

string

System.String

Y

一个字符数组

object

System.Object

Y

所有类型的基类型

dynamic

System.Object

Y

对于CLR, dynamic 和 object 完全一致。然而,C#编译器允许使用一个简单的语法,让dynamic变量参与动态调度。

checked 和 unchecked 的建议
  • 尽量使用有符号的数值类型(比如 Int32 和 Int64),而不要使用无符号的数值类型(比如 UInt32 和 UInt64),这允许编译器检测更多的上溢/下溢错误。
  • 如果代码发生不希望的溢出(可能因为无效的输入数据发生的),就把这些代码放在 checked 块中。同时还应捕捉 OverflowException。
  • 将允许发生溢出的代码显示的放在一个 unchecked 块中,比如一个计算校验和(checksum)的时候。
5.2
引用类型和值类型
引用类型
任何称为类的类型都是引用类型。
  • 引用类型总是从托管堆上分配
  • 对象中的其他字节总设为零
  • 从托管堆上分配一个对象时,可能强制执行一次垃圾收集操作
值类型
所有值类型都称为结构或枚举。
  • 值类型一般在线程栈上分配
  • 值类型并不包含一个指向实例的指针,相反,它包含了实例本身的字段,
  • 值类型的实例不受垃圾回收站的控制
  • 所有结构都是 System.ValueType 直接派生类,所有枚举都是从 System.Enum 的抽象类派生,后者又是从 System.ValueType 派生
值类型对象有两种表现形式:未装箱(unboxed)与已装箱(boxed),相反,引用类型总是处于已装箱形式。
5.3
值类型的装箱和拆箱

1装箱

    struct Point
    {
        public Int32 x, y;
    }

    public sealed class Program1
    {
        public static void Main()
        {
            ArrayList a = new ArrayList();
            Point p;
            for (int i = 0; i < 10; i++)
            {
                p.x = p.y = i;
                a.Add(p);  //对值类型进行装箱,并将引用添加到 ArrayList 中
            }

            Console.Read();
        }
    } 
Add 需要获取对托管堆的一个对象引用(或指针)作为参数。这里的 P 是一个结构(值类型),所以要使用装箱(boxing)。
在装箱操作时内部发生的事情:

1.在托管堆中分配内存。分配的内存量是值类型的各个字段需要的内存量加上托管堆的所有对象都有的两个额外成员(类型对象指针和同步索引块)需要的内存量。

2.值类型的字段赋值到新分配的堆内存。

3.返回对象的地址。值类型现在是一个引用类型。

2拆箱

拆箱就是一个获取指针的过程。事实上,指针指向的是已装箱实例中的未装箱部分。
            Int32 x = 5;
            Object o = x;
            Int16 y = (Int16)o; //抛出一个“InvalidCastException”类型的未经处理的异常 
只有将其转换为原先未装箱时的值类型——为 Int32
Int16 y = (Int16)(Int32)o;  //先拆箱为正确的类型,再转换

下面代码演示了涉及装箱和拆箱的几种情形

    class CLass2
    {
        static void Main()
        {
            Point p1 = new Point(10, 10);
            Point p2 = new Point(20, 20);

            //调用ToString(一个虚方法)时,不会对p1进行装箱
            Console.WriteLine(p1.ToString());

           //调用GetType(一个非虚方法)时,要对p进行装箱
            Console.WriteLine(p1.GetType());

            //第一次调用CompareTo时,不会对p1进行装箱
            //由于调用的是CompareTo(Point),所以对p2不会装箱
            Console.WriteLine(p1.CompareTo(p2));

            //p1要进行装箱,将引用放到c中
            IComparable c = p1;
            Console.WriteLine(c.GetType());

            //第二次调用CompareTo时,p1不需要装箱
            //由于向CompareTo传递的不是一个Point变量,所以调用CompareTo(object),要求获取一个已装箱的 Point 的引用
            //c不会装箱,因为它引用的本来就是一个已经装箱的 Point
            Console.WriteLine(p1.CompareTo(c));

            //第上次调用CompareTo时,C不需要装箱,因为它引用的本来就是一个已经装箱的Point
            //p2会被装箱,因为调用的是CompareTo(object)
            Console.WriteLine(c.CompareTo(p2));

            //对 c 进行拆箱,字段复制到 p2 中
            p2 = (Point)c;

            //证明字段已经复制到p2中
            Console.WriteLine(p2.ToString());
            Console.Read();
        }
    }

    internal struct Point : IComparable
    {
        private Int32 m_x, m_y;

        public Point(Int32 x, Int32 y)
        {
            m_x = x;
            m_y = y;
        }

        public override string ToString()
        {
            return string.Format("{0},{1}", m_x, m_y);
        }

        //实现类型安全的 CompareTo方法
        public Int32 CompareTo(Point other)
        {
            //使用勾股定力来计算哪个point的距离原点(0,0)更远
            return Math.Sign(
                Math.Sqrt(m_x * m_x + m_y * m_y) - Math.Sqrt(other.m_x * other.m_x + other.m_y * other.m_y)
                );
        }
        //实现IComparable的CompareTo方法
        public int CompareTo(object obj)
        {
            if (GetType() != obj.GetType())
            {
                throw new ArgumentException("obj is not a Point");
            }
            //调用类型安全的CompareTo方法
            return CompareTo((Point)obj);
        }
    } 
5.4
dynamic
许多时候程序需要处理一些运行时才会知晓的信息。许多开发者在使用C#时,要和一些不是用C#实现的组件通信,如 Python或Ruby。为了方便开发人员使用反射或者与基本组件通信,C#编辑器允许将一个表达式的类型标记为 dynamic。或者变量类型标记为 dynamic。可以用这个 dynamic 表达式/变量调用一个成员,比如字段。属性/索引器、方法、委托等等。编译器会生成特殊的IL代码来描述所需要的操作。这个特殊的代码称为 payload(有效载荷)。
    internal class DynamicDemo
    {
        static void Main()
        {
            for (int demo = 0; demo < 2; demo++)
            {
                dynamic arg = (demo == 0) ? (dynamic)5 : (dynamic)"A";
                dynamic result = Plus(arg);
                M(result); 
                //M(Int32):10 
                //M(String):AA
            }
            Console.Read();
        }

        private static dynamic Plus(dynamic arg) { return arg + arg; }
        private static void M(int n) { Console.WriteLine("M(Int32):" + n); }
        private static void M(string s) { Console.WriteLine("M(String):" + s); }
    } 
在字段类型、方法参数类型或方法返回类型被指定为 dynamic 前提下,编译器会将这个类型转为 System.Object,并在元数据中向字段、参数或返回类型应用  System.Runtime.CompilerServices.DynamicAttribute 的一个实例,局部变量类型也为 Object ,但不会应用 DynamicAttribute ,因为它使用限制在方法内。

《CLR via C#》读书笔记(5)基元类型、引用类型和值类型的更多相关文章

  1. [Clr via C#读书笔记]Cp5基元类型引用类型值类型

    Cp5基元类型引用类型值类型 基元类型 编译器直接支持的类型,基元类型直接映射到FCL中存在的类型. 作者希望使用FCL类型名称而避免使用关键字.他的理由是为了更加的清晰的知道自己写的类型是哪种.但是 ...

  2. CLR via C#(02)-基元类型、引用类型、值类型

    http://www.cnblogs.com/qq0827/p/3281150.html 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架 ...

  3. [CLR via C#]引用类型和值类型

    一.引用类型与值类型的区别 CLR支持两种类型:引用类型和值类型.引用类型总是从托管堆上分配的,C#的new操作符会返回对象的内存地址.使用引用类型时,必须注意到一些性能问题. 1)内存必须从托管堆上 ...

  4. 《CLR via C#》读书笔记--基元类型、引用类型和值类型

    编程语言的基元类型 编译器直接支持的数据类型称为基元类型.基元类型直接映射到Framework类库中存在的类型.例如:C#中的int直接映射到System.Int32类型.下表给出了C#基元类型与对应 ...

  5. CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

    编程语言的基元类型   某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1 ...

  6. <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型

    5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...

  7. 【CLR Via C#】第5章 基元类型、引用类型、值类型

    第二遍看这本书,决定记录一下加深印象. 1,基元类型 什么事基元类型?基元类型是直接映射到FrameWork类库(FCL)中存在的类型,编译器直接支持的数据类型.比如int直接映射到System.In ...

  8. 重温CLR(四)基元类型、引用类型、值类型

    编程语言的基元类型 编译器直接支持的数据类型称为基元类型(primitive type).基元类型直接映射到framework类型(fcl)中存在的类型. 下表列出fcl类型 从另一个角度,可以认为C ...

  9. CLR VIA C#: 基元类型、 引用类型 和 值类型

    一.基元类型 . 引用类型 和 值类型的区别: 1.基元类型(primitive type):编译器直接支持的数据类型: 基元类型 直接映射到 FCL 中存在的类型. C# 小写是基元类型,例如:st ...

随机推荐

  1. OpenCV图像Canny边缘检测

    Canny边缘检测 图像的边缘检测的原理是检测出图像中所有灰度值变化较大的点,而且这些点连接起来就构成了若干线条,这些线条就可以称为图像的边缘函数原型:     void cvCanny(       ...

  2. php处理数据库数据,每处理一个数据返回客户端显示当前状态的方法。

    php处理大量数据,每处理一个数据返回客户端显示当前状态的方法. 类似于dedecms生成静态页 想法: 客户端发送请求 服务器端接受请求,开始统计所需处理的数据量 将所需处理数据按一定规则排列,发送 ...

  3. 2016年10月12日--string、Math类、Random随机数、DateTime、异常保护

    string string.length; //得到string长度 string.Trim(); //去掉string前后的空格 string.TrimStart(); //去掉string前的空格 ...

  4. 转:bwa的使用方法

    bwa的使用需要两中输入文件:    Reference genome data(fasta格式 .fa, .fasta, .fna)    Short reads data (fastaq格式 .f ...

  5. redis安装与参数说明

    redis安装与参数说明 博客分类: redis redis 1.下载tcl8.6.1-src.tar.gz 和 redis-2.8.6.tar.gz: 2.安装: 1).安装tcl Java代码 收 ...

  6. 如何准确高效的获取数据库新插入数据的主键id

    例如我们新建了一张表UserInformation,字段如下Id,为主键,自增,其它字段Name,Pwd,Email 然后我们来执行一个新增插入操作: insert into UserInformat ...

  7. java 调用webservice的各种方法总结

    java 调用webservice的各种方法总结 几种流行的开源WebService框架Axis1,Axis2,Xfire,CXF,JWS比较 方法一:创建基于JAX-WS的webservice(包括 ...

  8. REACT 学习

    1.React/React Native 的ES5 ES6写法对照表 http://bbs.reactnative.cn/topic/15/react-react-native-%E7%9A%84es ...

  9. 【leetcode】Reverse Nodes in k-Group

    Reverse Nodes in k-Group Given a linked list, reverse the nodes of a linked list k at a time and ret ...

  10. appium + python 环境搭建

    所需:JDK.Android SDK.Appium服务程序.Appium客户端程序 1. 安装最新的JDK,并配置环境变量. JAVA_HOME=C:\Program Files (x86)\Java ...