Есть ли разница между объявлением и построением объекта типа значения? - PullRequest
3 голосов
/ 02 октября 2009

Я работаю в .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

Эти две строки делают что-то другое?


РЕДАКТИРОВАТЬ : Гуффа указал, что декларирование и конструирование не одно и то же. Следующий код демонстрирует это:

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 '

Ответы [ 3 ]

3 голосов
/ 02 октября 2009

Используя ключевое слово New в объявлении, вот так:

Dim c2 As New Coordinates

это просто сокращение для:

Dim c2 As Coordinates = New Coordinates()

Конструктор без параметров автоматически создается для структуры, и он просто возвращает значение со всеми свойствами, установленными в их значения по умолчанию (то есть все байты обнуляются), функционально эквивалентные:

Public Sub New()
   x = 0
   y = 0
   z = 0
End Sub

В VB все локальные переменные инициализируются при включении метода, поэтому переменная c1, объявленная без ключевого слова New, также обнуляется. Разница не видна, пока вы не выполните инструкцию более одного раза:

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)
2 голосов
/ 02 октября 2009

Для структуры всегда есть конструктор по умолчанию (без параметров) (объявлять его ошибочно).

для VB.Net (РЕДАКТИРОВАТЬ)

это то же самое;) см. здесь

для C #:

Разница между Coordinates c1; и Coordinates c2 = New Coordinates(); заключается в том, что для первого поля структуры остаются неназначенными, и объект нельзя использовать, пока все поля не будут инициализированы. Второй инициализирует все поля внутри объекта структуры.

Для получения дополнительной информации зайдите здесь , это очень подробно.

1 голос
/ 02 октября 2009

В 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

потому что этот конструктор 'зарезервирован'.

...