Невозможно увидеть членов структуры, объявленной как обнуляемую - PullRequest
3 голосов
/ 11 августа 2009

Почему в VB.NET я не вижу члена структуры, когда я делаю его обнуляемым типом?

Пример:

Public Structure myNullable  
    Dim myNullVar As Integer  
End Structure

Sub Main()  
    Dim myInstance As myNullable 'This works.  
    Dim myNullableInstance? As myNullable 'This works.   
    myInstance.myNullVar = 1  'This works.     
    myNullableInstance.myNullVar = 1   'This doesn't work.  
End Sub

Ответы [ 6 ]

3 голосов
/ 11 августа 2009

Как уже говорили другие, вам нужно использовать свойство Value, чтобы получить значение. Однако System.Nullable<T> является неизменным - свойство Value доступно только для чтения. Он будет возвращать копию значения, поэтому, даже если вы сможете изменить поле, оно не будет выполнять то, что вы хотите.

Это действительно хорошая вещь - типы значений должны быть неизменяемыми. Изменчивые структуры ужасны - если тот факт, что Nullable<T> затрудняет использование вашего типа, толкает вас на путь неизменности, это здорово.

Сделайте ваше поле доступным только для чтения и добавьте конструктор, который позволит вам передать значение. Затем вместо того, чтобы пытаться изменить нулевое значение, присвойте переменной совершенно новое значение.

1 голос
/ 11 августа 2009

Как уже отмечалось в других ответах, вы можете получить доступ к внутреннему значению обнуляемого значения с помощью .Value. Но они предлагают вам сделать myNullableInstance.Value.myNullVar = 1, который не работает.

Это из-за того, как работают структуры. Когда вы изменяете член структуры, создается новый экземпляр структуры. Вы не можете сделать это в этом случае, потому что это изменило бы свойство Value класса Nullable, что нельзя сделать напрямую, потому что Value - ReadOnly.

Это будет работать, хотя:

Dim myInstance as myNullable
myInstance.myNullVar = 1
myNullableInstance = myInstance
0 голосов
/ 30 апреля 2013

Обнуляемые структуры - это боль, и нет веской причины, по которой Microsoft должна усложнять ситуацию. Это сделано таким образом, чтобы облегчить работу авторам компилятора, а не пользователям языка.

На самом деле нет веской причины, по которой нам нужно, чтобы ссылочные типы и типы значений вели себя по-разному. Microsoft пытается скрыть логические указатели (адреса), но это работает не очень хорошо, потому что это усложняет, а не облегчает. Каждое правило и ограничение, налагаемое на язык, усложняет ситуацию и приводит к неэффективности, ошибкам во время выполнения и более высоким затратам на разработку.

Нам всем было бы лучше, если бы мы вернулись к логически типизированным указателям. Тогда нам не понадобятся такие красивые слова, как неизменные. (неизменный означает неизменный!)

Мое предложение состоит в том, чтобы отказаться от структур Nullable и сделать их классом, который всегда можно обнулять.

0 голосов
/ 11 августа 2009

Имеет смысл, что это не работает:

myNullableInstance.Value.myNullVar = 1

По сути, вы назначаете некоторую копию структуры, которая была возвращена свойством Value.

Это на самом деле не проблема, потому что обычно структуры создаются для того, чтобы быть неизменными в качестве лучшей практики. Вы можете обойти это с некоторыми заданиями туда и обратно, но, как уже сообщали другие, вы должны вместо этого пересмотреть использование класса. Таким образом, вам также не нужен Nullable, потому что вы можете просто использовать нулевую ссылку.

0 голосов
/ 11 августа 2009

Поскольку структура Nullable<T> предоставляет базовое значение через свойство Value. Поэтому вам необходимо:

myNullableInstance.Value.myNullVar = 1
0 голосов
/ 11 августа 2009

Когда тип обнуляем, вы должны проверять, имеет ли оно значение, а затем обращаться к этому значению, только если он есть:

if(myNullableInstance.hasValue)
myNullableInstance.value.myNullVar=1
...