(五)CSharp-结构

一、结构定义

使用类的这种方式来封装数据和功能,在性能方面会有一些损失。(由于托管堆的优化,性能损失比较小)如果有时只需要一个小的数据结构,不需要类的全部功能,最好使用结构。
所以,结构主要用于小的数据结构。

比如以下数据结构只有两个 double 数据类型:

 struct Dimensions
    {
        public double Length;
        public double Width;
    }

为结构定义函数与为类定义函数完全相同:

 struct Dimensions
    {
        public double Length;
        public double Width;

        public Dimensions(double length,double width)
        {
            Length = length;
            Width = width;
        }

        public double Diagonal
        {
            get
            {
                return Math.Sqrt(Length * Length + Width * Width);
            }
        }

    }

结构存储在栈中或存储为内联(inline)(如果它们是存储在堆中的另一个对象的一部分。注:书中此处是不是说引用类型对象中的一部分是结构?

结构特点:

  • 结构不支持继承。
  • 对于结构,构造函数的工作方式有些区别。尤其是编译器总是提供一个无参数的默认构造函数,它是不允许替换的。(此处书中意思是:如果程序员写出其默认构造函数,就会提示错误,而类就不会。我推测的原因是:结构去除了类在构造函数工作的一部分功能
  • 使用结构,可以指定字段如何在内存中布局。(第15章会介绍)

此外,我发现了书中没有提到一点的小知识:
结构中的所有普通数据成员都得通过构造函数里进行赋值,少一个都不行,会报错。

具体通过例子来说明:

//错误编译例子1
struct Dimensions
    {
        public double Length;
        public double Width;
        public Dimensions(double length, double width)
        {
            //此处报错,原因:没有对 Width 赋值
            //推测原因:也是去除了跟类相关的一部分可以自动处理数据成员的功能
            Length = length;
        }
    }

//正确编译例子2

   class  Student
    {
        public int Id;
        public string name;
        public Student(){ }
    }

    struct Dimensions
    {
        //除了静态变量和const常量,其他都不可赋初始值
        public Student Stud;
        public double Length ;
        public double Width;
        public readonly int readonlyInt;
        
        public const int ConstInt = 0;
        public static int StaticInt = 0;

        //此处错误,不能显式无参构造函数
        //public Dimensions() {  } 

        public Dimensions(double length, double width)
        {
            //在构造函数里,所有普通数据成员都必须赋初始值
            //思考:为什么结构的所有普通数据成员必须在构造函数里初始化值?
            //推测:因为结构去除了类自动对其成员进行赋初始值的功能
            Stud = new Student();
            Length = length;
            Width = width;
            readonlyInt = 0;
        }

        public Dimensions(double width)
        {
            //在构造函数里,所有普通数据成员都必须赋初始值
            Stud = new Student();
            Length = width;
            Width = width;
            readonlyInt = 2;
        }

    }

二、类和结构的区别:

结构和类的区别:

  • 类是引用类型,而结构是值类型。
  • 结构是隐式密封的,这意味着不能从它们派生其他结构。

结构是值类型

  • 结构类型的变量不能为 null
  • 两个结构变量不能引用同一对象

1、结构是值类型

  • 结构是值类型,而类是引用类型。(new 运算符是分配堆内存,所以不可用 new 来定义结构)
//错误例子
//定义 Dimensions 时,
//point 包含了一个未初始化的引用(不指向任何地方的一个地址),是错误的。
Dimensions point;
point.Length = 3;
point.Width = 6;

而如果结构定义为类的数据成员:

  class  Student
    {
        public int Id;
        public string name;
        public Dimensions point;
        public Student(){ }
    }

    struct Dimensions
    {
       
        public double Length ;
        public double Width;

        public Dimensions(double length, double width)
        {
          
            Length = length;
            Width = width;
          
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Student stud = new Student();
            //stud.point.Length 初始值默认为0
            Console.WriteLine(stud.point.Length);
            Console.ReadKey();
        }
    }

结构为值类型的优点:

  • 1)结构分配内存时,速度非常快,因为它们将内联或者保存在栈中。
  • 2)在结构超出了作用域被删除时,速度也很快,不需要等待垃圾回收。
    缺点:
  • 只要把结构作为参数来传递或者把一个结构赋予另一个结构(如 A=B,其中A和B是结构),结构的所有内容就被复制,而类只复制引用。
    (当把结构作为参数传递给方法时,应把它作为 ref 参数传递,以避免性能损失。此时只传递了结构在内存中的地址,这样传递速度就与在类中的传递速度一样快了。即跟类作为参数时一样的作用。)

2、结构与继承

结构不能被继承。

由于结构最终派生于类 System.Object,因此结构也可以访问 System.Object 的方法,甚至可以重写 System.Object 中的方法。

结构的继承链是:
每一个结构派生自 System.ValueType 类,System.ValueType 类又派生自 System.Object。ValueType 并没有给 Object 添加任何新成员,但提供了一些更适合结构的实现方式。

你可能感兴趣的:(CSharp,c#)