zoukankan      html  css  js  c++  java
  • 浅析C#中的结构体和类

    类和结构是 .NET Framework 中的常规类型系统的两种基本构造。 两者在本质上都属于数据结构。封装着一组总体作为一个逻辑单位的数据和行为。 数据和行为是该类或结构的“成员”,它们包括各自的方法、属性和事件等

    对于C/C++程序员来说。结构体和类的差别非常小。仅仅是结构体的默认成员变量为public,类的默认成员变量为private。

    可是对于C#来说,结构体和类有非常多的不同。

    首先来谈一谈为何须要结构体:
    最主要的原因就是结构体有能力去管理、使用不同数据类型的组合。

    .NET支持值类型和引用类型的概念,全部的C#内置类型中,除了string外均为值类型。

    在C#中,结构体是值类型。类是引用类型。

    值类型能够降低对堆的管理、使用。降低垃圾回收,表现出更好的性能。可是值类型也有不好的一面。比方会涉及到装箱拆箱等操作。

    以下定义一个结构体:

    public struct Foo
    {
        // Fields
        private string fooString;
        private int fooNumber;
        // Property
        public string FooString
        {
            get
            {
                return fooString;
            }
            set
            {
                fooString = value;
            }
        }
        // Method
        public int GetFooNumber()
        {
            return fooNumber;
        }
    }

    能够看到。结构体和类非常的类似。让我们更深层次的看看两者的不同。


    1继承
    结构体继承自System.ValueType,而类继承自System.Object。结构体不能继承其它的类或结构体,可是能够把结构体当做是接口。因为接口仅仅是用于引用类型的操作,所以把结构体当成接口就会隐式的发生装箱操作。

    比如例如以下代码:
    struct Foo : IFoo
    {
    int x;
    }
    IFoo iFoo = new Foo();

    2构造
    C#不同意结构体具有无參数的默认构造函数。原因是:对于值类型,编译器既不会生成默认构造函数。也不会调用默认构造函数。所以你不能这样初始化:

    struct MyWrongFoo
    {
        int x = 1;
    }

    可是你能够使用new:
    Foo foo = new Foo();
    这里须要注意的是,虽然使用了new操作,可是结构体分配在栈上,而不是堆上。更有趣的是,new操作没有调用无參数的构造函数。

    看看以下的代码:

    struct Foo
    {
        int x;
        public Foo(int x)
        {
            this.x = x;
        }
    }
    class FooTester
    {
        [STAThread]
        static void Main(string[] args)
        {
            Foo f = new Foo();
        }
    }

    这里我重载了构造函数。就能够使用new了。


    所以我们能够这样:
    调用 new Foo()
    调用重载的构造函数初始化
    显示的设置每一个值:
    Foo foo;
    foo.x = 0;

    3析构
    我们不能为结构体定义析构函数。

    4仅仅读关键字
    对于引用类型。readonly关键字阻止你将引用指到其它对象,可是无法阻止你改变该对象的状体。
    对于值类型来说。readonly关键字与C++中的const非常像。阻止你改变对象的状态。

    class MyReferenceType
    {
        int state;
        public int State
        {
            get
            {
                return state;
            }
            set
            {
                state = value;
            }
        }
    }
    struct MyValueType
    {
        int state;
        public int State
        {
            get
            {
                return state;
            }
            set
            {
                state = value;
            }
    }
        }
    class Program
    {
        readonly MyReferenceType myReferenceType = new MyReferenceType();
        readonly MyValueType myValueType = new MyValueType();
        public void SomeMethod()
        {
            myReferenceType = new MyReferenceType(); // Compiler Error
            myReferenceType.State = 1234; // Ok
            myValueType = new MyValueType(); // Compiler Error
            myValueType.State = 1234; // Compiler Error
        }
    }

    总结:
    为结构定义默认(无參数)构造函数是错误的。

    在结构体中初始化实例字段也是错误的。

    仅仅能通过两种方式初始化结构成员:一是使用參数化构造函数,二是在声明结构后分别訪问成员。 对于不论什么私有成员或以其它方式设置为不可訪问的成员,仅仅能在构造函数中进行初始化。

    假设使用 new 运算符创建结构对象。则会创建该结构对象。并调用适当的构造函数。

    与类不同,结构的实例化能够不使用 new 运算符。

    在此情况下不存在构造函数调用。因而能够提高分配效率。 可是,在初始化全部字段之前,字段将保持未赋值状态且对象不可用。

    当结构包括引用类型作为成员时,必须显式调用该成员的默认构造函数,否则该成员将保持未赋值状态且该结构不可用。 (这将导致编译器错误 CS0171。)

    对于结构。不像类那样存在继承。 一个结构不能从还有一个结构或类继承。并且不能作为一个类的基。 可是,结构从基类 Object 继承。

    结构可实现接口。其方式同类全然一样。

  • 相关阅读:
    HTTP 方法:GET 对比 POST
    js中return的用法
    Javascript:谈谈JS的全局变量跟局部变量
    ajax请求数据之后在已经有的数据前面打对勾的方法
    JS中的call()和apply()方法区别
    聚簇索引与非聚簇索引的区别
    Android开发(27)--TextView单击链接弹出Activity
    Android 4.2启动代码分析(一)
    Android重启应用程序代码
    java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7400382.html
Copyright © 2011-2022 走看看