zoukankan      html  css  js  c++  java
  • CLR via C# 第五章学习记录(更新中)

    1.设置全局溢出检查,项目属性->生成->高级->检测运算上溢/下溢
    2.局部使用溢出检测
    Byte b = 100;
    b = checked((Byte)(b + 200));// 不检测溢出
    checked// 检测溢出代码段
    {
    Byte b = 100;
    b = (Byte)(b + 200);
    }
    ——————————————————————————
    UInt32 invalid = unchecked((UInt32)(-1));// 检测溢出
    unchecked// 不检测溢出代码段
    {
    Byte b = 100;
    b = (Byte)(b + 200);
    }

    CLR支持2种类型:引用类型和值类型

    引用类型总是从托管堆分配,C#的new操作符返回对象内存地址——即指向对象的内存地址。使用引用类型必须留意性能问题。注意4个事实
    1.内存必须从托管堆分配(new的时候进行内存分配)
    2.堆上分配的每个对象都有一些额外成员,这些成员必须初始化。
    3.对象中的其他字节(为字段而设)总是设为0
    4.从托管堆分配对象时,可能强制执行一次垃圾回收
    引用类型和值类型的区别:
    任何称为“类”的类型都是引用类型。(如:System.Exception类,System.IO.FileStream类以及System.Radom类)
    所有值类型都称为结构或者枚举,(如:System.Int32结构,SystemBoolean结构,SystemDecimal结构,System.TimeSpan结构,System.DayOfWeek枚举,System.IO.FileAttributes枚举以及System.Drawing.FontStyle枚举)所有结构都是抽象类型System.ValueType的直接派生类。System.ValueType本身又直接从System.Object派生。根据定义,所有值类型都必须从System.ValueType派生。所有枚举都是从System.Enum抽象类型派生,后者又从System.ValueType派生。
    class SomeRef { public Int32 x;}// 所有的class都是引用类型
    struct SomeVal { public Int32 x;}// 所有的Struct都是值类型
    static void ValueTypeDemo() {
    SomeRef r1 = new SomeRef();// 在堆上分配
    SomeVal v1 = new SomeVal();// 在栈上分配
    r1.x = 5; // 提领指针
    v1.x = 5; // 在栈上修改
    Console.WriteLine(r1.x); // 显示5
    Console.WriteLine(v1.x); // 显示5
    //
    SomeRef r2 = r1; // 只复制引用(指针/地址)
    SomeVal v2 = v1; // 在栈上分配并复制成员
    r1.x = 8; // r1.x和r2.x都会更改
    v1.x = 9; // v1.x会更改,v2.x不变
    Console.WriteLine(r1.x); // 显示8
    Console.WriteLine(r2.x); // 显示8
    Console.WriteLine(v1.x); // 显示9
    Console.WriteLine(v2.x); // 显示5
    SomeVal v1=new SomeVal(); //在栈上分配,所有的字段初始化为0(已初始化)
    =>SomeVal v1; //在栈上分配,同样初始化为0(会认为v1未赋值)
    }

    将值类型变量赋给另一个值类型变量,会逐行逐字段的复制,将引用类型的变量赋给另一个引用类型的变量只复制内存地址。
    装箱是将值类型转换成引用类型,拆箱是将引用类型转换成值类型
    public static void Main() {
    Point p;
    p.x = p.y =1;
    Object o = p; // 对p装箱:o引用已装箱实例
    p = (Point) o; // 对o拆箱,将字段从已装箱实例复制到栈变量中,C#编译器将生成一条IL指令对o拆箱(获取毅装箱实例中的字段的地址),并生成另一条指令将这些字段从堆复制到基于栈的变量p中
    p.x = 2; // 更新栈变量状态
    o = p; // 对p装箱:o引用新的已装箱实例
    }

    要获取对值类型实例的引用,实例就必须装箱,将值类型实例传给需要获取引用类型的方法,就会发生这种情况

    public sealed class Program {
    public static void Main() {
    Int32 v = 5; // 创建未装箱的值类型变量
    #if INEFFICIENT
    // 编译下面这一行,v被装箱3次,浪费时间和内存
    Console.WriteLine("{0},{1},{2}", v, v, v);
    #else
    // 下面代码结果一样,但无论执行速度,还是内存利用,都比前面代码更胜一筹
    Object o = v; // 对v进行手动装箱(1次)
    // 编译下面这行不发生装箱
    Console.WriteLine("{0},{1},{2}", o, o, o);
    }
    }
  • 相关阅读:
    斐波那契数列
    用两个栈实现队列
    从尾到头打印链表
    HDOJ5877(dfs序+离散化+树状数组)
    HDOJ5876(补图的最短路)
    POJ3090(欧拉函数)
    POJ2478(欧拉函数)
    POJ2407(欧拉函数)
    POJ2142(扩展欧几里得)
    POJ3020(最小边覆盖)
  • 原文地址:https://www.cnblogs.com/zbfamily/p/6421417.html
Copyright © 2011-2022 走看看