我已经在.NET工作了一段时间了,但偶尔我仍然会对框架与我以前的C ++经验之间的差异感到困惑。
在.NET中,所有对象都是值类型或引用类型。引用类型在堆上分配,而值类型在堆栈上分配(无论如何,在当前的CLR实现中)。我明白了。但是,至少在VB.NET中,您仍然可以在值类型上定义构造函数。你可以这样做:
Public Structure Coordinates
Public x As Integer
Public y As Integer
Public z As Integer
Sub New(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer)
Me.x = x
Me.y = y
Me.z = z
End Sub
End Structure
使用此代码,我可以编写Dim c As Coordinates
然后自己访问c
的成员,或者我可以编写Dim c As New Coordinates(10, 20, 30)
。这两种方法有什么区别?显然new
关键字没有在堆上分配对象,因为它是一个值类型。我只是不清楚值类型的构造函数是否仅仅是一种方便,还是它们实际上执行除执行之外的其他任何方法。
或许让我的观点更清楚:我可以轻松删除上述代码中New
的定义,但我仍然可以这样做:
Dim c1 As Coordinates
Dim c2 As New Coordinates
这两行有什么不同吗?
编辑:Guffa指出声明和构建不相同。以下代码演示了这一点:
For i As Integer = 1 To 3
Dim c1 As Coordinates
Dim c2 As New Coordinates
c1.x += 1
c2.x += 1
Console.WriteLine("c1.x = {0}, c2.x = {1}", c1.x, c2.x)
Next
' output: '
' c1.x = 1, c2.x = 1 '
' c1.x = 2, c2.x = 1 '
' c1.x = 3, c2.x = 1 '
因此,在涉及迭代的场景中,表示值类型的局部变量不会在堆栈上重新分配;他们留下来。我使用普通的旧整数看了同样的场景,发现了同样的行为:
For i As Integer = 1 To 3
Dim x As Integer
Dim y As New Integer
x += 1
y += 1
Console.WriteLine("x = {0}, y = {1}", x, y)
Next
' output: '
' x = 1, y = 1 '
' x = 2, y = 1 '
' x = 3, y = 1 '
答案 0 :(得分:3)
在声明中使用New关键字,如下所示:
Dim c2 As New Coordinates
只是一个快捷方式:
Dim c2 As Coordinates = New Coordinates()
为结构自动创建无参数构造函数,它只返回一个值,所有属性都设置为默认值(即所有字节都清零),功能相当于:
Public Sub New()
x = 0
y = 0
z = 0
End Sub
在VB中,当您使用方法时,所有局部变量都会被初始化,因此在没有New关键字的情况下声明的变量c1也将被清零。在您多次执行语句之前,差异是不可见的:
For i As Integer = 1 to 3
Dim c1 As Coordinates
Dim c2 As New Coordinates
c1.x += 1
c2.x += 1
Console.WriteLine("c1.x = {0}, c2.x = {1}", c1.x, c2.x)
Next
输出:
c1.x = 1, c2.x = 1
c1.x = 2, c2.x = 1
c1.x = 3, c2.x = 1
c1变量只初始化一次,而每次执行语句时都会初始化c2变量。
由于结构值可以在不首先调用构造函数的情况下存在,因此结构构造函数大多是初始化结构的便捷方式。它比创建结构值的静态方法更整洁,但它的工作原理基本相同:
Public Shared Function Create(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer) As Coordinates
Dim item As Coordinates
item.x = x
item.y = y
item.z = z
Return item
End Function
Dim c3 As Coordinates = Coordinates.Create(1, 2, 3)
答案 1 :(得分:2)
结构总是有一个默认的(无参数)构造函数(声明它是一个错误)。
它是一样的;),见here
Coordinates c1;
和Coordinates c2 = New Coordinates();
之间的区别在于,对于第一个结构字段保持未分配状态,并且在初始化所有字段之前无法使用该对象。第二个初始化struct对象中的所有字段。
有关详细信息,请转到here,它非常详细。
答案 2 :(得分:1)
在VB.Net中,
Dim c1 As Coordinates
Dim c2 As New Coordinates
做同样的事情。在C#中,尝试使用c1.X会产生编译器(未分配)错误,而c2.X将为0。
根据VB规则,局部变量默认设置为0(或0.0或false或...),在C#中,它们被视为未分配。
构造函数的规则对于结构和类是不同的,您不能添加:
Sub New()
Me.x = 1
Me.y = 2
Me.z = 3
End Sub
因为这个构造函数是'保留'。