C#结构的注意事项 :
1. 结构是值类型,这意味这结构是存储在栈中的,结构存储的是变量的内容,而不是变量存储的地址(这是相当于引用类型的变量而言的)。将一个结构的实例赋值到另外一个结构实例时,会创建一个相同的内存副本,而不是创建一份结构的地址。这一点可以说是结构的本质了。
2. 结构中不能显式包含默认的无参的构造函数。注意是显式包含,如下的代码是错误的
代码
struct MyStruct
{
public MyStruct()
{
_field1 = 0;
_field2 = 0;
}
private int _field1;
public int Field1
{
get { return _field1; }
set { this._field1 = value; }
}
private int _field2;
public int Field2
{
get { return _field2; }
set { this._field2 = value; }
}
}
{
public MyStruct()
{
_field1 = 0;
_field2 = 0;
}
private int _field1;
public int Field1
{
get { return _field1; }
set { this._field1 = value; }
}
private int _field2;
public int Field2
{
get { return _field2; }
set { this._field2 = value; }
}
}
再看如下代码:
代码
struct MyStruct
{
private int _field1;
public int Field1
{
get { return _field1; }
set { this._field1 = value; }
}
private int _field2;
public int Field2
{
get { return _field2; }
set { this._field2 = value; }
}
}
class Program
{
public static void Main()
{
MyStruct myStruct = new MyStruct();
Console.WriteLine(myStruct.Field1 + " " + myStruct.Field2);
Console.ReadKey();
}
}
{
private int _field1;
public int Field1
{
get { return _field1; }
set { this._field1 = value; }
}
private int _field2;
public int Field2
{
get { return _field2; }
set { this._field2 = value; }
}
}
class Program
{
public static void Main()
{
MyStruct myStruct = new MyStruct();
Console.WriteLine(myStruct.Field1 + " " + myStruct.Field2);
Console.ReadKey();
}
}
以上代码是正确的,我们注意在Main方法中我们调用了结构体的默认无参构造函数,这不是与我们上面说的矛盾了吗?答案是不矛盾,因为就像我强调的不能显式包含无参构造函数,但C#却隐式包含了一个无参构造函数,该函数对结构体中所有的字段进行初始化,初始值为default指定的值。
3.不能对字段进行赋值,以下的代码是错误的:
struct MyStruct
{
//错误:不能对字段赋初值
private int _field1 = 0;
...
}
结构体所有字段初始化都必须在构造函数中进行,换句话说,如果你要定义带参数的构造函数,那你必须对所有的字段赋值,注意是字段。对于不想赋值的字段用default进行赋值,如下所示:
代码
struct MyStruct
{
public MyStruct(int field1, int field2)
{
_field1 = field1;
_field2 = field2;
}
{
public MyStruct(int field1, int field2)
{
_field1 = field1;
_field2 = field2;
}
//注意这里
public MyStruct(int field1) : this(field1, default(int))
{
_field1 = field1;
}
}
public MyStruct(int field1) : this(field1, default(int))
{
_field1 = field1;
}
}
4.最后要注意的一点是:结构体是没有终结器的。因为如果是局部变量,结构体是存储在栈上的。如果作为引用类型的一部分,此时存储在堆上,他的内存会随着引用类型的垃圾回收被清理。