zoukankan      html  css  js  c++  java
  • C#学习笔记6

    1.结构:结构除了可以含有属性和字段,还可以包方法和构造器,但不能包含黠认(无参数}的构造器。有的时候(比如在实例化一个数组的时候)不会调用值类型的构造器,因为所有数组内存都转为用零来初始化,为了避免因为默认构造器只是偶尔调用而造成不一致,C#完全禁止了用户显式定义默认构造器,因为编译器会将声明时的实例字段赋值放到类型的构造器中进行。在构造器中必须对 struct中的所有字段进行初始化,如果没有做到这一点,就会产生编译错误,可查看Angle结构的代码。

    2.结构的继承与接口:所有值类型都是密封的,除此之外,所有值类型都派生自system.ValueType,这意味着struct的继承链息是从object到ValueType到struct。值类型还能实现接口,许多接口都是实现接口框架固定组成部分,比如 IComparilble 和IFormattable。

    3.装箱与拆箱:装箱就是把值类型变成引用类型,如下:

     (1) 首先在堆中分配好内存,它将用于存放值类型的数据以及少许额外开销;

     (2) 接着发生一次内存复制动作,栈上的值类型数据复制到堆上分配好的位置;

     (3) 最后,对象或接口引用得到更新,指向堆上的位置;

      拆箱就是把引用类型变成值类型,如下:根据定义,CIL 指令 unbox 只是对堆上的数据进行解引用,并不包括从堆复制到栈的动作。但在 C#语言中,太多数时候紧接着在拆箱之后发生一次复制动作。装箱和拆箱之所以重要,是因为装箱去对性能和行为造成一些影响。开发者可以通过查看CIL,在一个特定的代码片段中统计 box/unbox 指令的数量。在BoxAndUnbox()中的代码就存在多次的装箱与拆箱,这样编写的代码是不合理。

    4.枚举:枚举和其他值类型稍有不同,因为枚举的继承链是从System.ValueType到System.Enum,再到enum。

    5.枚举与字符串的转换:枚举ToString()后会输出枚举标识符,使用Enum.Parse或Enum.TryParse方法可以把字符串转化为枚举,后一个方法是.Net4.0新增的泛型方法。此中我们也可以使用Enum.IsDefined()方法来检查一个值是否包含在一个枚举中。

    6.枚举作为“位标志”使用:

    (1)可以查看如下“FileAttributes“枚举的设定(即System.IO。FileAttributes的设定),作为位标志后,其值可以自由组合,所以可以使用Or运算符来联结枚举值。如本示例中BitFlag()方法的使用。当然枚举中的每个值不一定只对应一个标志,完全可以为常用的标志组合定义额外的枚举值。

    (2)使用位标志类型的时候,位标志枚举应该包含[FlagsAttribute]这个特性,这个标志指出多个枚举值可以组合使用,此外,它改变了ToString()和Parse()方法的行为。例如为一个已用FlagsAttribute修饰了的枚举调用ToString()方法,会为已设置的每个枚举标志输出对应的字符串(如BitFlag2()的示例),而如果没有这个修饰,返回的就是组合后数值。

    public struct Angle
    {
        public Angle(int hours, int minutes, int seconds)
        {
            Hours = hours;
            Minutes = minutes;
            Seconds = seconds;
        }
        public int Hours { get; set; }
        public int Minutes { get; set; }
        public int Seconds { get; set; }
    
        public Angle Move(int hours, int minutes, int seconds)
        {
            return new Angle(Hours + hours, Minutes + minutes, Seconds + seconds);
        }
    }
    
    [Flags]
    public enum FileAttributes
    {
        ReadOnly = 1 << 0,
        Hidden = 1 << 1,
        System = 1 << 2,
        Directory = 1 << 3,
        Archive = 1 << 5,
        Device = 1 << 6,
        Normal = 1 << 7,
        Temporary = 1 << 8,
        SparseFile = 1 << 9,
        ReparsePoint = 1 << 10,
        Compressed = 1 << 11,
        Offline = 1 << 12,
        NotContentIndexed = 1 << 13,
        Encrypted = 1 << 14
    }
    
    public void BitFlag()
    {
        string fileName = @"enumtest.txt";
        FileInfo file = new FileInfo(fileName);
        file.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly;
        Console.WriteLine("{0} | {1} = {2}", FileAttributes.Hidden, FileAttributes.ReadOnly, (int)file.Attributes);
        if ((file.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
        {
            throw new Exception("File is not hidden");
        }
        if ((file.Attributes & FileAttributes.ReadOnly) != FileAttributes.ReadOnly)
        {
            throw new Exception("File is not read-only");
        }
        //....
    }
    
    public void BitFlag2()
    {
        string fileName = @"enumtest.txt";
        FileInfo file = new FileInfo(fileName);
        file.Open(FileMode.Create).Close();
        FileAttributes startingAttributes = file.Attributes;
        file.Attributes = FileAttributes.Hidden | FileAttributes.ReadOnly;
        Console.WriteLine(""{0}" output as "{1}"", file.Attributes.ToString().Replace(",", "|"), file.Attributes);
        FileAttributes attributes;
        Enum.TryParse(file.Attributes.ToString(), out attributes);
        Console.WriteLine(attributes);
        File.SetAttributes(fileName, startingAttributes);
        file.Delete();
    }
    
    public void BoxAndUnbox()
    {
        int totalCount;
        ArrayList list = new ArrayList();
        Console.Write("Enter a number between 2 to 1000:");
        totalCount = int.Parse(Console.ReadLine());
        list.Add((double)0);
        list.Add((double)1);
        for (int i = 2; i < totalCount; i++)
        {
            list.Add((double)list[i - 1] + (double)list[i - 2]);
        }
        foreach (double num in list)
        {
            Console.Write("{0},", num);
        }
    }

    ----------------------以上内容根据《C#本质论 第三版》进行整理

  • 相关阅读:
    SQLServer多表联查,多表分页查询
    GOF23种设计模式概括
    常用的正则表达式
    面向对象七大原则
    Jquery简单学习
    MVC图片上传详解
    面向对象OOP概念描述
    C++ 基础命名空间 using namespace std;
    找不到WJSWDLL.dll
    AspectJ中的类型间声明(成员注入)
  • 原文地址:https://www.cnblogs.com/zwt-blog/p/6305833.html
Copyright © 2011-2022 走看看