.NET中的结构和类有什么区别?
当前回答
类中声明的事件通过锁(this)自动锁定其+=和-=访问,以使其线程安全(静态事件根据类的类型锁定)。结构中声明的事件没有自动锁定其+=和-=访问。结构的锁(this)无法工作,因为只能锁定引用类型表达式。创建结构实例不能导致垃圾收集(除非构造函数直接或间接创建引用类型实例),而创建引用类型的实例会导致垃圾收集。结构始终具有内置的公共默认构造函数。类DefaultConstructor{静态空隙Eg(){直接yes=新的直接();//始终编译正常InDirect可能=新InDirect();//如果构造函数存在且可访问,则编译//...}}这意味着结构总是可实例化的,而类可能不是,因为它的所有构造函数都可以是私有的。类不可实例化{private NonInstantiable()//确定{}}结构Direct{private Direct()//编译时错误{}}结构不能有析构函数。析构函数只是对象的重写。伪装完成,结构作为值类型,不受垃圾收集的影响。结构Direct{~Direct(){}//编译时错误}InDirect类{~InDirect(){}//编译正常}~Indirect()的CIL如下所示:.method家族hidebysig虚拟实例无效Finalize()cil已管理{// ...}//方法结束间接::Finalize结构是隐式密封的,类不是。结构不能是抽象的,类可以。结构不能在其构造函数中调用:base(),而没有显式基类的类可以。结构不能扩展另一个类,类可以。结构不能声明类可以声明的受保护成员(例如,字段、嵌套类型)。结构不能声明抽象函数成员,抽象类可以。结构不能声明虚函数成员,类可以。结构不能声明密封的函数成员,类可以。结构不能声明重写函数成员,类可以。此规则的一个例外是,结构可以重写System.Object的虚拟方法,即Equal()、GetHashCode()和ToString()。
其他回答
基元值类型或结构类型的每个变量或字段都持有该类型的唯一实例,包括其所有字段(公共和私有)。相比之下,引用类型的变量或字段可能为空,或者可能引用存储在其他位置的对象,其他引用也可能存在。结构的字段将存储在与该结构类型的变量或字段相同的位置,该变量或字段可能位于堆栈上,也可能是另一个堆对象的一部分。
创建原始值类型的变量或字段将使用默认值创建它;创建结构类型的变量或字段将创建一个新实例,以默认方式创建其中的所有字段。创建引用类型的新实例将首先以默认方式创建其中的所有字段,然后根据类型运行可选的附加代码。
将一个基本类型的变量或字段复制到另一个将复制值。将结构类型的一个变量或字段复制到另一个变量将前一个实例的所有字段(公共和私有)复制到后一个实例。将一个引用类型的变量或字段复制到另一个将导致后者引用与前者相同的实例(如果有的话)。
需要注意的是,在某些语言(如C++)中,类型的语义行为与它的存储方式无关,但在.NET中则不是这样。如果一个类型实现了可变值语义,则将该类型的一个变量复制到另一个变量会将第一个实例的财产复制到第二个实例所引用的另一个实例,并且使用第二个实例的成员来变异它将导致第二个例子被改变,而不是第一个。如果一个类型实现了可变的引用语义,那么将一个变量复制到另一个变量并使用第二个变量的成员来变异对象将影响第一个变量所引用的对象;具有不可变语义的类型不允许变异,因此复制是创建新实例还是创建对第一个实例的另一个引用在语义上无关紧要。
在.NET中,值类型可以实现上述任何语义,前提是它们的所有字段都可以这样做。然而,引用类型只能实现可变引用语义或不可变语义;具有可变引用类型字段的值类型限于实现可变引用语义或奇怪的混合语义。
首先,结构是通过值而不是引用传递的。结构适用于相对简单的数据结构,而类通过多态性和继承从体系结构的角度来看具有更大的灵活性。
其他人可能会比我给你更多的细节,但当我所追求的结构很简单时,我会使用结构。
为了使其完整,使用Equals方法时还有另一个不同之处,它由所有类和结构继承。
假设我们有一个类和一个结构:
class A{
public int a, b;
}
struct B{
public int a, b;
}
在Main方法中,我们有4个对象。
static void Main{
A c1 = new A(), c2 = new A();
c1.a = c1.b = c2.a = c2.b = 1;
B s1 = new B(), s2 = new B();
s1.a = s1.b = s2.a = s2.b = 1;
}
然后:
s1.Equals(s2) // true
s1.Equals(c1) // false
c1.Equals(c2) // false
c1 == c2 // false
因此,结构适用于类似数字的对象,例如点(保存x和y坐标)。课程适合其他人。即使两个人的名字、身高、体重。。。,他们还是两个人。
类中声明的事件通过锁(this)自动锁定其+=和-=访问,以使其线程安全(静态事件根据类的类型锁定)。结构中声明的事件没有自动锁定其+=和-=访问。结构的锁(this)无法工作,因为只能锁定引用类型表达式。创建结构实例不能导致垃圾收集(除非构造函数直接或间接创建引用类型实例),而创建引用类型的实例会导致垃圾收集。结构始终具有内置的公共默认构造函数。类DefaultConstructor{静态空隙Eg(){直接yes=新的直接();//始终编译正常InDirect可能=新InDirect();//如果构造函数存在且可访问,则编译//...}}这意味着结构总是可实例化的,而类可能不是,因为它的所有构造函数都可以是私有的。类不可实例化{private NonInstantiable()//确定{}}结构Direct{private Direct()//编译时错误{}}结构不能有析构函数。析构函数只是对象的重写。伪装完成,结构作为值类型,不受垃圾收集的影响。结构Direct{~Direct(){}//编译时错误}InDirect类{~InDirect(){}//编译正常}~Indirect()的CIL如下所示:.method家族hidebysig虚拟实例无效Finalize()cil已管理{// ...}//方法结束间接::Finalize结构是隐式密封的,类不是。结构不能是抽象的,类可以。结构不能在其构造函数中调用:base(),而没有显式基类的类可以。结构不能扩展另一个类,类可以。结构不能声明类可以声明的受保护成员(例如,字段、嵌套类型)。结构不能声明抽象函数成员,抽象类可以。结构不能声明虚函数成员,类可以。结构不能声明密封的函数成员,类可以。结构不能声明重写函数成员,类可以。此规则的一个例外是,结构可以重写System.Object的虚拟方法,即Equal()、GetHashCode()和ToString()。
类的实例存储在托管堆上。“包含”实例的所有变量都只是对堆上实例的引用。将对象传递给方法会导致传递引用的副本,而不是对象本身。
结构(从技术上讲,值类型)存储在使用它们的任何地方,很像原始类型。运行时可以随时复制内容,而无需调用自定义的复制构造函数。将值类型传递给方法涉及复制整个值,同样无需调用任何自定义代码。
C++/CLI名称使这种区别更加明显:“ref class”是第一个类,“value class”是第二个类。C#使用的关键字“class”和“struct”只是必须学习的东西。
推荐文章
- AutoMapper:“忽略剩下的?”
- 如何找出一个文件存在于c# / .NET?
- string. isnullorempty (string) vs. string. isnullowhitespace (string)
- 完全外部连接
- 如何使用。net 4运行时运行PowerShell ?
- 在foreach循环中编辑字典值
- 使用System.IO.Compression在内存中创建ZIP存档
- 在WPF中引入一个窗口到前面
- .NET用固定的空格格式化字符串
- 我如何获得和设置环境变量在c# ?
- Linq风格的“For Each”
- 我如何得到一个动画gif在WPF工作?
- 什么时候使用记录、类和结构
- 获取程序集名称
- “\n”与“Environment”的区别。换行符