关于结构

结构的用法

一、为什么使用结构,而不是类?

    结构可以像类一样,封装有各种数据、类型和函数成员。不过与类不同的是,它是一个值类型。假设有一个类:

        
class Size
    {
        int Width;
        int Height;
    }

    这个类只是存储两个int类型的数据而已,而没有别的意义,在这种情况下,为了获得更好的性能,可以使用结构为定义:

        
struct Size
    {
        public int Width;
        public int Height;
    }

    为什么说结构具有比类更好的性能?这是因为结构是值类型,其数据存放在栈或存储为内联(inline)中(如果它是对象的一部分,则也会保存在堆中),其分配更快于引用类型,且当其值离开作用域时就会立即被收回。

    不过,如果把结构作为参数来传递,或把一个结构赋值给另一个结构时,就会大量地复制结构的内容,如果结构的内容很大,则系统的开销是非常大的。所以从这个角度上来说,结构只适合于较小的数据。

    有一个方法可以避免当结构做为参数传递时,会涉及到大量的数据被复制的问题,那就是把结构做为ref参数来传递。这样只传递结构在内存中的地址,即引用,而不会复制数据。

二、结构与继承

    结构本身不支持继承,但却可以提供一个或多个接口来实现。

    结构隐式地继承自System.ValueType,而后者又继承自System.Object类,所以结构能访问System.Object类中的三个方法:Equals()、ToString()、GetHashTable(),包括重写,比如,一个较有用的就是重写ToString()方法。看下面的例子:

        
class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Size s= new Size();
            s.Width = 2;
            s.Height = 3;
            //最后的输出是2+3
            Console.WriteLine(s.ToString());
            Console.ReadLine();
        }
    }

    public struct Size
    {
        public int Width;
        public int Height;

        public override string ToString()
        {
            return Width.ToString() + "+" + Height.ToString();
        }
    }

三、结构的构造函数

    结构提供了默认的构造函数,而且把所有字段隐式地初始化为0;比如上面的这个结构,会自动地把Width和herght初始化为0。因此,在定义结构时,不能够定义字段的初始值以绕开默认的构造函数。比如下面这段代码将不会编译通过(但如果是类就可以):

        
public struct Size
    {
        public int Width = 2;
        public int Height = 3;

        public override string ToString()
        {
            return Width.ToString() + "+" + Height.ToString();
        }
    }

    同时,也不能声明不带参数的构造函数(因为默认的构造函数并不带有参数),但可以像类一样结构提供除了默认以外的构造函数,以对其字段进行初始化,比如如下代码:

        
class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Size s1 = new Size();
            Size s2 = new Size(2,3);

            //最后的输出是0+0
            Console.WriteLine(s1.ToString());

            //最后的输出是2+3
            Console.WriteLine(s2.ToString());
            Console.ReadLine();
        }
    }

    public struct Size
    {
        public int Width;
        public int Height;

        public Size(int intWidth,int intHeight)
        {
            this.Width = intWidth;
            this.Height = intHeight;
        }

        public override string ToString()
        {
            return Width.ToString() + "+" + Height.ToString();
        }
    }

    声明结构时,可以像类一样使用new关键字,则系统会自动初始化结构并分配内存(注意:在这里使用new关键字,并不是创建一个实例,因为这不是类)。也可以不使用new关键字,如果不使用则一样可以声明,但却没有进行初始化(当然已经分配空间了),看以下代码:

        
class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            Size s1 = new Size();
            Size s2;       

            //如果没有这两句,s2.ToString()将会出错,因为没有初始化变量(s2)。
            s2.Width=2;
            s2.Height = 3;

            //最后的输出是0+0
            Console.WriteLine(s1.ToString());

            //最后的输出是2+3
            Console.WriteLine(s2.ToString());
            Console.ReadLine();
        }
    }

    public struct Size
    {
        public int Width;
        public int Height;

        public override string ToString()
        {
            return Width.ToString() + "+" + Height.ToString();
        }
    }

    结构可以像类一样提供Close()和Dispose()方法,但不能提供Finaliza()方法,因为此方法是应用于对象,由垃圾收集器调用,而结构是值类型,所以无法调用此方法。

    结构的任何成员不允许声明为virtual,因为结构不允许被继承;也不允许声明为abstract,因为结构不允许成为其他类的基类;同时,也不允许使用关键字sealed,因为它是隐式密封的,已默认为sealed。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值