Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 1 |

 

  Вопрос: ArrayList(index).property Добавлено: 29.05.04 21:22  

Автор вопроса:  danser | ICQ: 299287824 

Dim AList As New ArrayList()
Public Structure a
   Dim Check As Windows.Forms.CheckState
   Dim Name As String
End Structure

Dim c1 As a
c1.Check = CheckState.Checked
c1.Name = "1"
AList.Add(c1)

'Читает вроде нормально
msgbox(AList(0).name)
'А вот с присвоением не проходит, ПОЧЕМУ? и что делать?
AList(0).name = "123"

'Исключение
An unhandled exception of type 'System.Exception' occurred in microsoft.visualbasic.dll
Additional information: Latebound assignment to a field of value type 'a' is not valid when 'a'
is the result of a latebound expression.

Ответить

  Ответы Всего ответов: 9  

Номер ответа: 1
Автор ответа:
 Андрей Щёкин [darxeth]



ICQ: 161560107 

Вопросов: 9
Ответов: 52
 Web-сайт: www.livejournal.com/users/darxeth_digital
 Профиль | | #1
Добавлено: 30.05.04 00:08

Ну, во-первых, надо всегда ставить Option Strict On. Тогда не будет странных ошибок времени выполнения.

Но этот код (с присвоением) всё равно не будет работать как надо. Твоя структура a - значимый тип (value type), в ArrayList'е он хранится в упакованнов (boxed) виде. Для того, чтобы использовать свойство этой структуры, необходимо произвести её распаковку (unboxing). Распаковка происходит при приведении типа AList(0) от Object к a, которое будет ясно видно с включённым Option Strict.

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

Тут есть только два решения - либо использовать объект вместо структуры, либо заменять сразу всю структуру. Это можно сделать так: AList(0) = New a("123", CheckState.Checked), если, конечно, написать соответствующий конструтор.

Ответить

Номер ответа: 2
Автор ответа:
 danser



ICQ: 299287824 

Вопросов: 76
Ответов: 209
 Профиль | | #2 Добавлено: 30.05.04 13:08

Делал через обект. Клас реализующий мой обект:

Public Class TestClass

    Public name As String

    Public check As Windows.Forms.CheckState

End Class

Затем в програмном коде:

Dim c1 As New TestClass()

c1.name = "1"

c1.check = CheckState.Checked

AList.Add(c1)

 

MsgBox(CType(AList(0), TestClass).name)

CType(AList(0), TestClass).name = "123"

MsgBox(CType(AList(0), TestClass).name)

Ответить

Номер ответа: 3
Автор ответа:
 danser



ICQ: 299287824 

Вопросов: 76
Ответов: 209
 Профиль | | #3 Добавлено: 30.05.04 14:51

Все конечно хорошо но вот какая проблема.
Я заранее не знаю какой тип обекта. То есть я знаю что свойство  .Name, а тип мне неизвесный, a CType требует тип непосредственнo. Что делать то есть как передать тип в CType через параметр? Приведенная ниже инструкция не работает

sub(byref AList as ArrayList, TypeObject as Type)
...
CType(Alist(0),TypeObject).name="123"
...
end sub

Ответить

Номер ответа: 4
Автор ответа:
  Артём Л.



ICQ: 280044491 

Вопросов: 43
Ответов: 227
 Профиль | | #4 Добавлено: 30.05.04 15:28
если у классов есть свойство Name но нет общего предка (и он не
предполагается) для превидения, то возможно нужно воспользоваться
интерфейсом и приводить к нему, например

Interface Int
property Name as String
end Interface

class class1
implements Int
public property Name implements Int.Name
Set()
Get()
end property
end class

class class2
implements Int
public property Name implements Int.Name
Set()
Get()
end property
end class

ну и потом CType(AList(0), Int).name = "123" не зависимо от типа AList(0)

между прочим объявлять так "Public name As String" в классах немного
противоречит принципам правильного ООП



Ответить

Номер ответа: 5
Автор ответа:
 danser



ICQ: 299287824 

Вопросов: 76
Ответов: 209
 Профиль | | #5 Добавлено: 30.05.04 20:12

Про интерфейсы только слышал но ничего конкретного не знал, спасибо ща буду испитывать...

<между прочим объявлять так "Public name As String" в классах <немного противоречит принципам правильного ООП
А как не противоречит?

Ответить

Номер ответа: 6
Автор ответа:
 Андрей Щёкин [darxeth]



ICQ: 161560107 

Вопросов: 9
Ответов: 52
 Web-сайт: www.livejournal.com/users/darxeth_digital
 Профиль | | #6
Добавлено: 30.05.04 22:21

Да и совсем противоречит.
Должно быть:

Private theName As String

Public Property Name() As String
   Get
      Return theName
   End Get
   Set(ByVal value As String)
      theName = value
   End Set
End Property

Классы не должны иметь публично доступных полей.

Кстати, я согласен, что все эти CType - это . Но пока приходится либо писать свою коллекцию, либо всё время писать CType (кстати, DirectCast должен работать быстрее). Только в VB 2005 это сделают почеловечески.

Ответить

Номер ответа: 7
Автор ответа:
 danser



ICQ: 299287824 

Вопросов: 76
Ответов: 209
 Профиль | | #7 Добавлено: 31.05.04 16:55

Да получается, спасибо всем очень помогли.  Замечание:

1. Если интерфейс обявляется не в одном модуле то надо указывать Public Interface Int что бы потом(в моем случае интерфейс и клас его использующий находятся в разних проектах) иметь к нему доступ, а то, как я понял, по умолчанию там Private.

2.  У меня так не идет:  public property Name implements Int.Name 
а идет так:
Public Property Name() As String Implements Int.Name

3. На щёт правильного ООП то я понял что надо через property но иногда лень матушка писать лишний код.

Ответить

Номер ответа: 8
Автор ответа:
  Артём Л.



ICQ: 280044491 

Вопросов: 43
Ответов: 227
 Профиль | | #8 Добавлено: 31.05.04 18:03
извинии конечно за погрешности, я просто код набирал не в студии а прямо в
письме, так что мог что-то и упустить...



Ответить

Номер ответа: 9
Автор ответа:
 Андрей Щёкин [darxeth]



ICQ: 161560107 

Вопросов: 9
Ответов: 52
 Web-сайт: www.livejournal.com/users/darxeth_digital
 Профиль | | #9
Добавлено: 01.06.04 01:42
А лишнего кода здесь и нет ;), это всё окупится. Кстати, тебя никто и не заставляет это писать вручную. Я обычно генерю представление класса из объявлений вида:
    Name: String
    SomeProperty: SomeType
скриптом на perl'е. Но вовсе не обязательно изучать перл, есть наверняка куча готовых утилит, которые из одной строчки всё делают (плагинов к VS, в первую очередь). Мне сейчас просто лень искать.

Или макрос напиши.

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам