.NET中的结构和类有什么区别?
当前回答
在.NET中,有两类类型,引用类型和值类型。
结构是值类型,类是引用类型。
一般的区别是,引用类型存在于堆中,值类型存在于内联中,也就是说,在定义变量或字段的任何位置。
包含值类型的变量包含整个值类型值。对于结构,这意味着变量包含整个结构及其所有字段。
包含引用类型的变量包含指针,或对内存中实际值所在位置的引用。
首先,这有一个好处:
值类型始终包含值引用类型可以包含空引用,这意味着它们此刻根本不引用任何内容
在内部,引用类型被实现为指针,并且知道变量赋值是如何工作的,还有其他行为模式:
将值类型变量的内容复制到另一个变量中,将整个内容复制到新变量中,使这两个变量不同。换句话说,复制后,对其中一个的更改不会影响另一个将一个引用类型变量的内容复制到另一个变量中,就会复制引用,这意味着现在有两个引用指向实际数据的同一个存储位置。换句话说,在复制之后,更改一个引用中的数据似乎也会影响另一个引用,但这只是因为您实际上只是在两个地方查看相同的数据
当您声明变量或字段时,以下是两种类型的区别:
变量:值类型位于堆栈上,引用类型位于堆栈中,作为指向堆内存中实际内存所在位置的指针(请注意EricLipperts系列文章:堆栈是一个实现细节)类/结构字段:值类型完全位于类型内部,引用类型位于类型内部作为指向堆内存中实际内存所在位置的指针。
其他回答
从微软在类和结构之间的选择。。。
根据经验,框架中的大多数类型应该是类。然而,在某些情况下值类型的特性使其更适合使用结构。✓ 考虑结构而不是类:如果该类型的实例很小并且通常很短,或者通常嵌入在其他对象中。X避免结构,除非该类型具有以下所有属性特点:它在逻辑上表示单个值,类似于原始类型(int、double等)。它的实例大小小于16字节。它是不可变的。(无法更改)它不必经常装箱。
如前所述:类是引用类型,而结构是具有所有后果的值类型。
根据经验,框架设计指南建议在以下情况下使用结构而不是类:
它的实例大小小于16字节它逻辑上表示单个值,类似于原始类型(int、double等)它是不可变的它不必经常装箱
为了使其完整,使用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坐标)。课程适合其他人。即使两个人的名字、身高、体重。。。,他们还是两个人。
类的实例存储在托管堆上。“包含”实例的所有变量都只是对堆上实例的引用。将对象传递给方法会导致传递引用的副本,而不是对象本身。
结构(从技术上讲,值类型)存储在使用它们的任何地方,很像原始类型。运行时可以随时复制内容,而无需调用自定义的复制构造函数。将值类型传递给方法涉及复制整个值,同样无需调用任何自定义代码。
C++/CLI名称使这种区别更加明显:“ref class”是第一个类,“value class”是第二个类。C#使用的关键字“class”和“struct”只是必须学习的东西。
在.NET中,结构和类声明区分引用类型和值类型。
传递引用类型时,实际存储的只有一个。访问实例的所有代码都在访问同一个实例。
传递值类型时,每个值类型都是副本。所有代码都在自己的副本上运行。
这可以用一个例子来说明:
struct MyStruct
{
string MyProperty { get; set; }
}
void ChangeMyStruct(MyStruct input)
{
input.MyProperty = "new value";
}
...
// Create value type
MyStruct testStruct = new MyStruct { MyProperty = "initial value" };
ChangeMyStruct(testStruct);
// Value of testStruct.MyProperty is still "initial value"
// - the method changed a new copy of the structure.
对于一个班级来说,这将是不同的
class MyClass
{
string MyProperty { get; set; }
}
void ChangeMyClass(MyClass input)
{
input.MyProperty = "new value";
}
...
// Create reference type
MyClass testClass = new MyClass { MyProperty = "initial value" };
ChangeMyClass(testClass);
// Value of testClass.MyProperty is now "new value"
// - the method changed the instance passed.
类可以是空的-引用可以指向空。
结构是实际值-它们可以为空,但决不能为空。因此,结构总是有一个没有参数的默认构造函数——它们需要一个“起始值”。