当前位置: 代码迷 >> C# >> 浅析C#中的结构体跟类
  详细解决方案

浅析C#中的结构体跟类

热度:84   发布时间:2016-05-05 03:04:16.0
浅析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 继承。 结构可实现接口,其方式同类完全一样。

版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案