C#中结构与类的区别

文章1:

Title目录

  类与结构的实例比较

  类与结构的差别

  如何选择结构还是类   

  一.类与结构的示例比较:

  结构示例:

  public struct Person

  {

  string Name;

  int height;

  int weight

  public bool overWeight()

  {

  //implement something

  }

  }

  类示例:

  public class TestTime

  {

  int hours;

  int minutes;

  int seconds;

  

  public void passtime()

  {

  //implementation of behavior

  }

  }

  调用过程:

  public class Test

  {

  public static ovid Main

  {

  Person Myperson=new Person //声明结构

  TestTime Mytime=New TestTime //声明类

  }

  }

  从上面的例子中我们可以看到,类的声明和结构的声明非常类似,只是限定符后面是 struct 还是 class 的区别,而且使用时,定义新的结构和定义新的类的方法也非常类似。那么类和结构的具体区别是什么呢?   

  二 .类与结构的差别

  1. 值类型与引用类型

  结构是值类型:值类型在堆栈上分配地址,所有的基类型都是结构类型,例如:int 对应System.int32 结构,string 对应 system.string 结构 ,通过使用结构可以创建更多的值类型

  类是引用类型:引用类型在堆上分配地址

  堆栈的执行效率要比堆的执行效率高,可是堆栈的资源有限,不适合处理大的逻辑复杂的对象。所以结构处理作为基类型对待的小对象,而类处理某个商业逻辑

  因为结构是值类型所以结构之间的赋值可以创建新的结构,而类是引用类型,类之间的赋值只是复制引用

  注:

  1.虽然结构与类的类型不一样,可是他们的基类型都是对象(object),c#中所有类型的基类型都是object

  2.虽然结构的初始化也使用了New 操作符可是结构对象依然分配在堆栈上而不是堆上,如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用

  2.继承性

  结构:不能从另外一个结构或者类继承,本身也不能被继承,虽然结构没有明确的用sealed声明,可是结构是隐式的sealed .

  类:完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也能被继承

  注:虽然结构不能被继承 可是结构能够继承接口,方法和类继承接口一样

  例如:结构实现接口

  interface IImage  

  {

  void Paint();

  }
  

  struct Picture : IImage

  {

  public void Paint()

  {

  // painting code goes here

  }

  private int x, y, z; // other struct members

  }
  

  3.内部结构

  结构:

  没有默认的构造函数,但是可以添加构造函数

  没有析构函数

  没有 abstract 和 sealed(因为不能继承)

  不能有protected 修饰符

  可以不使用new 初始化

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

  类:

  有默认的构造函数

  有析构函数

  可以使用 abstract 和 sealed

  有protected 修饰符

  必须使用new 初始化   

  三.如何选择结构还是类

  讨论了结构与类的相同之处和差别之后,下面讨论如何选择使用结构还是类:

  1. 堆栈的空间有限,对于大量的逻辑的对象,创建类要比创建结构好一些

  2. 结构表示如点、矩形和颜色这样的轻量对象,例如,如果声明一个含有 1000 个点对象的数组,则将为引用每个对象分配附加的内存。在此情况下,结构的成本较低。

  3. 在表现抽象和多级别的对象层次时,类是最好的选择

  4. 大多数情况下该类型只是一些数据时,结构时最佳的选择
目录

  类与结构的实例比较

  类与结构的差别

  如何选择结构还是类   

  一.类与结构的示例比较:

  结构示例:

  public struct Person

  {

  string Name;

  int height;

  int weight

  public bool overWeight()

  {

  //implement something

  }

  }

  类示例:

  public class TestTime

  {

  int hours;

  int minutes;

  int seconds;

  

  public void passtime()

  {

  //implementation of behavior

  }

  }

  调用过程:

  public class Test

  {

  public static ovid Main

  {

  Person Myperson=new Person //声明结构

  TestTime Mytime=New TestTime //声明类

  }

  }

  从上面的例子中我们可以看到,类的声明和结构的声明非常类似,只是限定符后面是 struct 还是 class 的区别,而且使用时,定义新的结构和定义新的类的方法也非常类似。那么类和结构的具体区别是什么呢?   

  二 .类与结构的差别

  1. 值类型与引用类型

  结构是值类型:值类型在堆栈上分配地址,所有的基类型都是结构类型,例如:int 对应System.int32 结构,string 对应 system.string 结构 ,通过使用结构可以创建更多的值类型

  类是引用类型:引用类型在堆上分配地址

  堆栈的执行效率要比堆的执行效率高,可是堆栈的资源有限,不适合处理大的逻辑复杂的对象。所以结构处理作为基类型对待的小对象,而类处理某个商业逻辑

  因为结构是值类型所以结构之间的赋值可以创建新的结构,而类是引用类型,类之间的赋值只是复制引用

  注:

  1.虽然结构与类的类型不一样,可是他们的基类型都是对象(object),c#中所有类型的基类型都是object

  2.虽然结构的初始化也使用了New 操作符可是结构对象依然分配在堆栈上而不是堆上,如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用

  2.继承性

  结构:不能从另外一个结构或者类继承,本身也不能被继承,虽然结构没有明确的用sealed声明,可是结构是隐式的sealed .

  类:完全可扩展的,除非显示的声明sealed 否则类可以继承其他类和接口,自身也能被继承

  注:虽然结构不能被继承 可是结构能够继承接口,方法和类继承接口一样

  例如:结构实现接口

  interface IImage  

  {

  void Paint();

  }
  

  struct Picture : IImage

  {

  public void Paint()

  {

  // painting code goes here

  }

  private int x, y, z; // other struct members

  }
  

  3.内部结构

  结构:

  没有默认的构造函数,但是可以添加构造函数

  没有析构函数

  没有 abstract 和 sealed(因为不能继承)

  不能有protected 修饰符

  可以不使用new 初始化

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

  类:

  有默认的构造函数

  有析构函数

  可以使用 abstract 和 sealed

  有protected 修饰符

  必须使用new 初始化   

  三.如何选择结构还是类

  讨论了结构与类的相同之处和差别之后,下面讨论如何选择使用结构还是类:

  1. 堆栈的空间有限,对于大量的逻辑的对象,创建类要比创建结构好一些

  2. 结构表示如点、矩形和颜色这样的轻量对象,例如,如果声明一个含有 1000 个点对象的数组,则将为引用每个对象分配附加的内存。在此情况下,结构的成本较低。

  3. 在表现抽象和多级别的对象层次时,类是最好的选择

  4. 大多数情况下该类型只是一些数据时,结构时最佳的选择
文章二:
Title

C# Corner今天发表了Bechir Bejaoui的一篇文章《What really make difference between structures and classes?》。关于结构和类的区别其实是老生常谈,不过本文总结得较为全面,所以翻译过来给大家共享。

总结起来,两者共有如下区别:

1、结构是值类型,类则是引用类型。因此前者是放在栈(Stack)里,后者则仅仅是将引用地址存放在栈里,而具体的值则存放在堆(heap)里。如下图所示:

2、据第1点可以得出结论,那就是类对象通常用来传递大数据,而结构对象则用来传递小数据。
3、类可以被继承,而结构则不支持。
4、结构对象不能像类对象一样赋值为null。
5、结构不能像类一样定义析构器。
6、结构不能像类一样定义为抽象的。
7、在结构中不能重写方法,除非是object类型的如下方法:

  • Equals()
  • GetHashCode()
  • GetType()
  • ToString()
若要让结构具有多态特性,可以让其实现接口。
8、在类中定义的事件是线程安全的,而结构则不是。
9、结构总是具有一个默认的公共无参构造函数,但去不能像类一样定义私有的无参构造函数:
    struct Me
    {
        private Me()
// compile-time error
       
{
        }
    }
    
    class
Me
    {
        private Me() // runs Ok
{
    }

10、类中的静态构造函数会被调用,而结构却不能。因此在结构中定义的静态构造函数,虽然可以编译通过,但却没有价值:
    struct myStructure
    {
        static myStructure()
        {
            Console.WriteLine("This is me a structure");
        }
    }
    class myClass

    {
        static myClass()
        {
            Console.WriteLine("This is me a class");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
           myStructure s = new myStructure();
//Nothing happen
           myClass c = new myClass();
//Will out put This is me a class
           Console
.Read();
        }
    }

11、结构不能像类一样定义volatile字段。volatile字段主要用于并发,它相当于方法体的lock。
12、可以对结构类型使用sizeof,对类则不行。
13、类的字段会被自动初始化为0/false/null,而结构则不能。
14、在结构中不能直接对字段初始化,而类则可以。
    struct myStructure
    {
        public string x = 2;
//Not allowed
    }
    class
myClass
    {
        public string x = 2;
//Allowed
    }

15、结构和类对于System.Object.Equals()方法的体现是不相同的。例如定义这样的结构和类:
    struct StructurePerson
    {
        public string FirstName;
        public string LastName;
    }
    class
ClassPerson
    {
        public string FirstName;
        public string LastName;
    }

如果运行如下的代码:

    class Program
    {
        static void Main(string[] args)
        {
            StructurePerson strX = new StructurePerson();
            strX.LastName = "Bejaoui";
            strX.FirstName = "Bechir";
            StructurePerson strY = new StructurePerson();
            strY.LastName = "Bejaoui";
            strY.FirstName = "Bechir";

            if (strX.Equals(strY))
            {
                Console.WriteLine("strX = strY");
            }
           
else
            {
                Console.WriteLine("strX != strY");
            }//This code displays strX = strY

            ClassPerson clsX = new ClassPerson();
            clsX.LastName = "Bejaoui";
            clsX.FirstName = "Bechir";
            ClassPerson clsY = new ClassPerson();
            clsY.LastName = "Bejaoui";
            clsY.FirstName = "Bechir";

            if (clsX.Equals(clsY))
            {
                Console.WriteLine("clsX = clsY");
            }
           
else
            {
                Console.WriteLine("clsX != clsY");
           
}//This code displays clsX != clsY
            Console.Read();
        }
    }

由于结构类型是值类型,因而Equals()方法比较的是两个对象的值是否相等,如果相等则返回true;而类类型为引用类型,Equals()方法比较的是二者的引用地址(即指针)是否相等。很显然,clsX和clsY是两个不同的对象,它们在栈的地址是不相等的。如果修改代码如下:

            ClassPerson clsX = new ClassPerson();
            clsX.LastName = "Bejaoui";
            clsX.FirstName = "Bechir";
            ClassPerson clsY = clsX;
            if (clsX.Equals(clsY))
            {
                Console.WriteLine("clsX = clsY");
           
}
           
else
            {
                Console.WriteLine("clsX != clsY");

            }//This code displays clsX = clsY

由于是直接将clsX赋值给clsY,因此两个对象的引用地址相等,Equals()方法返回true。

 

其实对于值类型和引用类型的相等性比较,是一个比较复杂的问题。例如我们可以通过重写Equals()方法增强或修改比较逻辑。重写Equals()方法还必须重写GetHashCode()方法。对于引用类型,还可以使用静态方法ReferenceEquals()方法。此外,还可以重载操作符==。另外,对于String对象,则比较特殊,因为它使用了Immutable模式。虽然String类型是引用类型,但如果直接定义的两个String对象的值相同,由于采用了Immutable模式的原因,这两个对象其实是同一个对象,引用地址是相同的。因此不仅动态方法Equals()返回的是true,且静态方法ReferenceEquals()返回的也是true。

C# Corner今天发表了Bechir Bejaoui的一篇文章《What really make difference between structures and classes?》。关于结构和类的区别其实是老生常谈,不过本文总结得较为全面,所以翻译过来给大家共享。

总结起来,两者共有如下区别:

1、结构是值类型,类则是引用类型。因此前者是放在栈(Stack)里,后者则仅仅是将引用地址存放在栈里,而具体的值则存放在堆(heap)里。如下图所示:

2、据第1点可以得出结论,那就是类对象通常用来传递大数据,而结构对象则用来传递小数据。
3、类可以被继承,而结构则不支持。
4、结构对象不能像类对象一样赋值为null。
5、结构不能像类一样定义析构器。
6、结构不能像类一样定义为抽象的。
7、在结构中不能重写方法,除非是object类型的如下方法:

  • Equals()
  • GetHashCode()
  • GetType()
  • ToString()

若要让结构具有多态特性,可以让其实现接口。
8、在类中定义的事件是线程安全的,而结构则不是。
9、结构总是具有一个默认的公共无参构造函数,但去不能像类一样定义私有的无参构造函数:
    struct Me
    {
        private Me()
// compile-time error
       
{
        }
    }
    
    class
Me
    {
        private Me() // runs Ok
{
    }

10、类中的静态构造函数会被调用,而结构却不能。因此在结构中定义的静态构造函数,虽然可以编译通过,但却没有价值:

    struct myStructure
    {
        static myStructure()
        {
            Console.WriteLine("This is me a structure");
        }
    }
    class myClass

    {
        static myClass()
        {
            Console.WriteLine("This is me a class");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
           myStructure s = new myStructure();
//Nothing happen
           myClass c = new myClass();
//Will out put This is me a class
           Console
.Read();
        }
    }

11、结构不能像类一样定义volatile字段。volatile字段主要用于并发,它相当于方法体的lock。
12、可以对结构类型使用sizeof,对类则不行。
13、类的字段会被自动初始化为0/false/null,而结构则不能。
14、在结构中不能直接对字段初始化,而类则可以。
    struct myStructure
    {
        public string x = 2;
//Not allowed
    }
    class
myClass
    {
        public string x = 2;
//Allowed
    }

15、结构和类对于System.Object.Equals()方法的体现是不相同的。例如定义这样的结构和类:
    struct StructurePerson
    {
        public string FirstName;
        public string LastName;
    }
    class
ClassPerson
    {
        public string FirstName;
        public string LastName;
    }

如果运行如下的代码:

    class Program
    {
        static void Main(string[] args)
        {
            StructurePerson strX = new StructurePerson();
            strX.LastName = "Bejaoui";
            strX.FirstName = "Bechir";
            StructurePerson strY = new StructurePerson();
            strY.LastName = "Bejaoui";
            strY.FirstName = "Bechir";

            if (strX.Equals(strY))
            {
                Console.WriteLine("strX = strY");
            }
           
else
            {
                Console.WriteLine("strX != strY");
            }//This code displays strX = strY

            ClassPerson clsX = new ClassPerson();
            clsX.LastName = "Bejaoui";
            clsX.FirstName = "Bechir";
            ClassPerson clsY = new ClassPerson();
            clsY.LastName = "Bejaoui";
            clsY.FirstName = "Bechir";

            if (clsX.Equals(clsY))
            {
                Console.WriteLine("clsX = clsY");
            }
           
else
            {
                Console.WriteLine("clsX != clsY");
           
}//This code displays clsX != clsY
            Console.Read();
        }
    }

由于结构类型是值类型,因而Equals()方法比较的是两个对象的值是否相等,如果相等则返回true;而类类型为引用类型,Equals()方法比较的是二者的引用地址(即指针)是否相等。很显然,clsX和clsY是两个不同的对象,它们在栈的地址是不相等的。如果修改代码如下:

            ClassPerson clsX = new ClassPerson();
            clsX.LastName = "Bejaoui";
            clsX.FirstName = "Bechir";
            ClassPerson clsY = clsX;
            if (clsX.Equals(clsY))
            {
                Console.WriteLine("clsX = clsY");
           
}
           
else
            {
                Console.WriteLine("clsX != clsY");

            }//This code displays clsX = clsY


由于是直接将clsX赋值给clsY,因此两个对象的引用地址相等,Equals()方法返回true。

 

其实对于值类型和引用类型的相等性比较,是一个比较复杂的问题。例如我们可以通过重写Equals()方法增强或修改比较逻辑。重写Equals()方法还必须重写GetHashCode()方法。对于引用类型,还可以使用静态方法ReferenceEquals()方法。此外,还可以重载操作符==。另外,对于String对象,则比较特殊,因为它使用了Immutable模式。虽然String类型是引用类型,但如果直接定义的两个String对象的值相同,由于采用了Immutable模式的原因,这两个对象其实是同一个对象,引用地址是相同的。因此不仅动态方法Equals()返回的是true,且静态方法ReferenceEquals()返回的也是true。

posted @ 2010-05-02 22:27  海军  阅读(253)  评论(0编辑  收藏  举报