C#中的结构与类
发布:张逸 | 发布时间: 2009年3月3日C# Corner今天发表了Bechir Bejaoui的一篇文章《What really make difference between structures and classes?》。关于结构和类的区别其实是老生常谈,不过本文总结得较为全面,所以翻译过来给大家共享。
总结起来,两者共有如下区别:
1、结构是值类型,类则是引用类型。因此前者是放在栈(Stack)里,后者则仅仅是将引用地址存放在栈里,而具体的值则存放在堆(heap)里。如下图所示:

2、据第1点可以得出结论,那就是类对象通常用来传递大数据,而结构对象则用来传递小数据。 { class Program class Program if (strX.Equals(strY)) ClassPerson clsX = new ClassPerson(); if (clsX.Equals(clsY)) ClassPerson clsX = new ClassPerson();
3、类可以被继承,而结构则不支持。
4、结构对象不能像类对象一样赋值为null。
5、结构不能像类一样定义析构器。
6、结构不能像类一样定义为抽象的。
7、在结构中不能重写方法,除非是object类型的如下方法:
若要让结构具有多态特性,可以让其实现接口。
8、在类中定义的事件是线程安全的,而结构则不是。
9、结构总是具有一个默认的公共无参构造函数,但却不能像类一样定义私有的无参构造函数(结构也不能再定义公共的无参构造函数,这与类不相同):
struct Me
{
private Me() // compile-time error
{
}
}
class Me
{
private Me() // runs Ok{
}
10、类中的静态构造函数会被调用,而结构却不能。因此在结构中定义的静态构造函数,虽然可以编译通过,但却没有价值:
{
static myStructure()
{
Console.WriteLine("This is me a structure");
}
}
class myClass
static myClass()
{
Console.WriteLine("This is me a class");
}
}
{
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();
}
}
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;
}
如果运行如下的代码:
{
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";
{
Console.WriteLine("strX = strY");
}
else
{
Console.WriteLine("strX != strY");
}//This code displays strX = strY
clsX.LastName = "Bejaoui";
clsX.FirstName = "Bechir";
ClassPerson clsY = new ClassPerson();
clsY.LastName = "Bejaoui";
clsY.FirstName = "Bechir";
{
Console.WriteLine("clsX = clsY");
}
else
{
Console.WriteLine("clsX != clsY");
}//This code displays clsX != clsY
Console.Read();
}
}
clsX.LastName = "Bejaoui";
clsX.FirstName = "Bechir";
ClassPerson clsY = clsX;
if (clsX.Equals(clsY))
{
Console.WriteLine("clsX = clsY");
}
else
{
Console.WriteLine("clsX != clsY");
由于是直接将clsX赋值给clsY,因此两个对象的引用地址相等,Equals()方法返回true。
其实对于值类型和引用类型的相等性比较,是一个比较复杂的问题。例如我们可以通过重写Equals()方法增强或修改比较逻辑。重写Equals()方法还必须重写GetHashCode()方法。对于引用类型,还可以使用静态方法ReferenceEquals()方法。此外,还可以重载操作符==。另外,对于String对象,则比较特殊,因为它使用了Immutable模式。虽然String类型是引用类型,但如果直接定义的两个String对象的值相同,由于采用了Immutable模式的原因,这两个对象其实是同一个对象,引用地址是相同的。因此不仅动态方法Equals()返回的是true,且静态方法ReferenceEquals()返回的也是true。
- 相关文章:
泛型的一点遗憾 (2009-2-14 9:48:21)
- 1.realyoyy
- 老大!拜托!
一般翻译
图里面的
Stack栈 Heap堆吧?张逸 于 2009-3-3 17:04:02 回复拜托,我是这样翻译的啊。Stack是栈(一种说法是堆栈),而Heap是堆。
没有错啊! - 2009-3-3 16:17:58 回复该留言
- 2.Eri
- 标题应该扩充,C#中的结构VS类。
因为有些只是C#不允许,不是CLR。
比如9.张逸 于 2009-3-3 18:30:38 回复Right. Corrected. Thanks. - 2009-3-3 18:27:52 回复该留言
- 4.pzmg
- 9、结构总是具有一个默认的公共无参构造函数,但去不能像类一样定义私有的无参构造函数:
struct Me
{
private Me() // compile-time error
{
}
}
其实你定义一个公共的五参的构造函数也是不对的.如果你要手动实现结构的构造函数,必须代参数张逸 于 2009-3-3 22:56:42 回复你说得对。我在文中补充了你的观点。 - 2009-3-3 21:55:52 回复该留言
- 6.Eri
- 这个网站页面在FF下有点问题,评论部分看不到。张逸 于 2009-3-4 10:21:19 回复这个问题我也发现了,不过如果你将Firefox升级到3.0,就没有任何问题了。呵呵:)
- 2009-3-4 10:02:00 回复该留言
发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。






张逸(Bruce Zhang)
