C#中的结构与类

简介:

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

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

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

 

2、据第1点可以得出结论,那就是类对象通常用来传递大数据,而结构对象则用来传递小数据。
3、类可以被继承,而结构则不支持。
4、结构对象不能像类对象一样赋值为null。
5、结构不能像类一样定义析构器。
6、结构不能像类一样定义为抽象的。
7、在结构中不能重写方法,除非是object类型的如下方法:
若要让结构具有多态特性,可以让其实现接口。
8、在类中定义的事件是线程安全的,而结构则不是。
9、结构总是具有一个默认的公共无参构造函数,但却不能像类一样定义私有的无参构造函数(结构也不能再定义公共的无参构造函数,这与类不相同):
    struct Me
    {
        private Me() 
// compile-time error
        
{
        }
    }
     
    class
 
Me
    {
        private Me() // runs Ok
{
    }

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

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

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

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

 

    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();
        }
    }

 

    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();
        }
    }

 

            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

 

 

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






本文转自wayfarer51CTO博客,原文链接:http://blog.51cto.com/wayfarer/280101,如需转载请自行联系原作者

相关文章
|
26天前
|
开发框架 .NET C#
C#|.net core 基础 - 删除字符串最后一个字符的七大类N种实现方式
【10月更文挑战第9天】在 C#/.NET Core 中,有多种方法可以删除字符串的最后一个字符,包括使用 `Substring` 方法、`Remove` 方法、`ToCharArray` 与 `Array.Copy`、`StringBuilder`、正则表达式、循环遍历字符数组以及使用 LINQ 的 `SkipLast` 方法。
|
2月前
|
存储 C# 索引
C# 一分钟浅谈:数组与集合类的基本操作
【9月更文挑战第1天】本文详细介绍了C#中数组和集合类的基本操作,包括创建、访问、遍历及常见问题的解决方法。数组适用于固定长度的数据存储,而集合类如`List<T>`则提供了动态扩展的能力。文章通过示例代码展示了如何处理索引越界、数组长度不可变及集合容量不足等问题,并提供了解决方案。掌握这些基础知识可使程序更加高效和清晰。
73 2
|
23天前
|
Java 程序员 C#
【类的应用】C#应用之派生类构造方法给基类构造方法传参赋值
【类的应用】C#应用之派生类构造方法给基类构造方法传参赋值
9 0
|
2月前
|
C# 数据安全/隐私保护
C# 一分钟浅谈:类与对象的概念理解
【9月更文挑战第2天】本文从零开始详细介绍了C#中的类与对象概念。类作为一种自定义数据类型,定义了对象的属性和方法;对象则是类的实例,拥有独立的状态。通过具体代码示例,如定义 `Person` 类及其实例化过程,帮助读者更好地理解和应用这两个核心概念。此外,还总结了常见的问题及解决方法,为编写高质量的面向对象程序奠定基础。
24 2
|
3月前
|
C#
C#中的类和继承
C#中的类和继承
40 6
|
3月前
|
Java C# 索引
C# 面向对象编程(一)——类
C# 面向对象编程(一)——类
33 0
|
3月前
|
开发框架 .NET 编译器
C# 中的记录(record)类型和类(class)类型对比总结
C# 中的记录(record)类型和类(class)类型对比总结
|
5月前
|
开发框架 .NET 编译器
程序与技术分享:C#基础知识梳理系列三:C#类成员:常量、字段、属性
程序与技术分享:C#基础知识梳理系列三:C#类成员:常量、字段、属性
36 2
|
5月前
|
C#
C# 版本的 计时器类 精确到微秒 秒后保留一位小数 支持年月日时分秒带单位的输出
这篇2010年的文章是从别处搬运过来的,主要包含一个C#类`TimeCount`,该类有多个方法用于处理时间相关的计算。例如,`GetMaxYearCount`计算以毫秒为单位的最大年数,`GetCurrentTimeByMiliSec`将当前时间转换为毫秒,还有`SecondsToYYMMDDhhmmss`将秒数转换为年月日时分秒的字符串。此外,类中还包括一些辅助方法,如处理小数点后保留一位数字的`RemainOneFigureAfterDot`。
|
5月前
|
存储 安全 C#
C# 类的深入指南
C# 类的深入指南