• .NET中类和结构的区别


    类:
    类是引用类型在堆上分配,类的实例进行赋值只是复制了引用,都指向同一段实际对象分配的内存
    类有构造和析构函数
    类可以继承和被继承
    结构:
    结构是值类型在栈上分配(虽然栈的访问速度比较堆要快,但栈的资源有限放),结构的赋值将分配产生一个新的对象。
    结构没有构造函数,但可以添加。结构没有析构函数
    结构不可以继承自另一个结构或被继承,但和类一样可以继承自接口

    结构体和类同样能够定义字段,方法和构造函数,都能实例化对象,这样看来结构体和类的功能好像是一样的了,但是他们在数据的存储上是不一样的(以下摘录):
    C#结构体和类的区别问题:在C#编程语言中,类属于引用类型的数据类型,结构体属于值类型的数据类型,这两种数据类型的本质区别主要是各自指向的内存位置不同。传递类的时候,主要表现为是否同时改变了源对象。
    C#结构体和类的区别技术要点:
        ◆类在传递的时候,传递的内容是位于托管内存中的位置,结构体在传递的时候,传递的内容是位于程序堆栈区的内容。当类的传递对象修改时,将同时修改源对象,而结构体的传递对象修改时,不会对源对象产生影响。
        ◆在一个类中,可以定义默认的、不带参数的构造函数,而在结构体中不能定义默认的、不带参数的构造函数。两者都可以定义带有参数的构造函数,通过这些参数给各自的字段赋值或初始化
    代码运行如下:类中赋值以后,两个对象中的值都发生变化,而结构体原来对象的值为发生变化

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace 类对象
    {
        //枚举  
        public enum Gender
        {
            男,
            女
        }
        //结构体
        public struct stuPerson
        {
            public string stuName;
            public int stuAge;
            public Gender stuSex;
            public void stuSayHello()
            {
                Console.WriteLine("我是{0},年龄{1},性别{2}", stuName, stuAge, stuSex);
            }
    
            //必须定义有参数的构造函数
            public stuPerson(string name, int age, Gender sex)
            {
                this.stuName = name;
                this.stuAge = age;
                this.stuSex = sex;
            }
    
        }
        class Program
        {
            static void Main(string[] args)
            {
                //实例化类
                Person Liuxiang = new Person();  //无参数的构造函数实例化的对象
                Liuxiang.Name = "刘翔";
                Liuxiang.Age = 30;
                Liuxiang.Sex = Gender.男;
                Liuxiang.SayHello();
                //声明另一个实例
                Person LXSon = Liuxiang;
                LXSon.Age = 10;
                //查看类 LiuXiang 和 LXSon中字段的值
                Console.WriteLine("LiuXiang 年龄{0}", Liuxiang.Age.ToString());  //10
                Console.WriteLine("LXSon 年龄{0}", LXSon.Age.ToString());    //10
    
                Console.WriteLine();
                //结构体
                stuPerson YaoMing = new stuPerson("姚明",33,Gender.男);
                YaoMing.stuSayHello();
                stuPerson YMSon = YaoMing;
                YMSon.stuAge = 13;
                //查看结构体中 YaoMing 和 YMSon中字段的值
                Console.WriteLine("YaoMing 年龄{0}", YaoMing.stuAge.ToString());  //10
                Console.WriteLine("YMSon 年龄{0}", YMSon.stuAge.ToString());    //10
    
                Console.ReadLine();
            }
        }
    
        class Person
        {
            //定义字段
            public string Name;
            public int Age;
            public Gender Sex;
    
            //定义方法
            public void SayHello()
            {
                Console.WriteLine("我是{0},年龄{1},性别{2}", this.Name, this.Age, this.Sex);
            }
            //无参数的构造函数
            public Person()
            {
    
            }
            //有参数的构造函数
            public Person(string name, int age, Gender sex)
            {
                this.Name = name;
                this.Age = age;
                this.Sex = sex;
            }
        }
    }

    总结起来,两者共有如下区别:
    1、结构是值类型,类则是引用类型。因此前者是放在栈(Stack)里,后者则仅仅是将引用地址存放在栈里,而具体的值则存放在堆(heap)里。如下图所示:
     
    2、据第1点可以得出结论,那就是类对象通常用来传递大数据,而结构对象则用来传递小数据。
    3、类可以被继承,而结构则不支持。
    4、结构对象不能像类对象一样赋值为null。
    5、结构不能像类一样定义析构器。
    6、结构不能像类一样定义为抽象的。
    7、在结构中不能重写方法,除非是object类型的如下方法:

    1. Equals()
    2. GetHashCode()   
    3. GetType()    
    4. 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 codedisplays clsX = clsY  

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

  • 相关阅读:
    【xamarin + MvvmCross 从零开始】一、环境安装
    .NET微服务从0到1:服务容错(Polly)
    .NET微服务从0到1:服务注册与发现(Consul)
    .NET微服务从0到1:API网关(Ocelot)
    .NET Core之单元测试(四):Fluent Assertions的使用
    .NET Core之单元测试(三):Mock框架Moq的使用
    .NET Core之单元测试(二):使用内存数据库处理单元测试中的数据库依赖
    .NET Core之单元测试(一):入门
    win+navicat
    JDBC介绍和Mybatis运行原理及事务处理
  • 原文地址:https://www.cnblogs.com/vaevvaev/p/8466121.html
Copyright © 2020-2023  润新知