:: Меню ::

Головна
  • Про сайт
  • Введення
  • Середовище програмування VB .NET: Visual Studio .NET
  • Вирази, оператори і передача управління
  • Класи і об'єкти
  •  Спадкоємство і інтерфейси
  • Обробка подій і делегати
  • Обробка помилок в VB .NET
  • Форми Windows, графічний вивід і друк
  • Уведення-виведення
  •  Багатопотокові застосування
  • Підтримка баз-даних в VB .NET
  • Короткий огляд ASP .NET
  • Складки .NET, установка додатків і COM Interop
  • Книга для гостей
    Контакти
    Добавити у вибране

    :: Друзі ::

     
     

    :: Лічильники ::

    = =

     

     

     

     

    Хэш-таблицы

    Прості і динамічні масиви зручні перш за все тим, що ви можете безпосередньо звернутися до будь-якого елементу по індексу. Звичайно, для цього необхідно знати індекс. У наступній структурі даних — хэш-таблице — довільний доступ до даних здійснюється по ключу. Допустимо, у вас є хэш-таблица з ім'ям thedata. Команда thedata("Bill 's Address") дозволяє витягувати з хэш-таблицы потрібний елемент без циклічного перебору всього вмісту. Хэш-таблицы дуже зручні в ситуаціях, коли ви хочете дістати швидкий доступ до значення по пов'язаному з ним унікальному атрибуту, тобто ключу. Зрозуміло, програмування хэш-таблицы — завдання непросте [ Для цього необхідно побудувати хорошу функцію хешування для обчислення індексу даних по ключу, а також вирішити неминучу проблему колізій, тобто збіги хэш-кодов у двох різних елементів. Навіть термінологія виглядає страхітливо... ], але, на щастя, ця робота вже виконана за вас розробниками .NET Framework.

    Іншу категорію структур даних, призначених для вибірки значення по ключу, складають асоціативні масиви (словники). Вони часто реалізуються у вигляді хэш-таблиц з додатковим кодом для виконання особливих операцій (наприклад, виявлення значень, що повторюються, або ключів).

    У таблиці. 4.4 перераховані найважливіші методи класу Hashtable (за повним списком звертайтеся до електронної документації).

    Методи класу Hashtable враховують регістр символів в строкових ключах, і дія команди Option Compare Text на них не розповсюджується. Про те, як створити хэш-таб-лицу, що ігнорує регістр символів, розказано в розділі 5.

    Таблиця 4.4. Найважливіші методи класу Hashtable

    Ім'я

    Опис

    Add

    Додає нову пару «ключ/значення» в хэш-таблицу

    Clear

    Видаляє з хэш-таблицы весь вміст

    Containskey

    Перевіряє, чи містить хэш-таблица заданий ключ (з урахуванням регістра символів)

    Containsvalue Соруто

    Перевіряє, чи містить хэш-таблица задане значення (з урахуванням регістра символів)

    Копіює елементи хэш-таблицы в масив

    Count

    Повертає кількість пар «ключ/значення» в хэш-таблице

    Item

     

    Властивість за умовчанням. Отримує або задає значення, пов'язане з вказаним ключем

    Keys

    Повертає всі ключі хэш-таблицы у вигляді колекції, вміст якої перебирається в циклі For-each

    Remove

    Видаляє з хэш-таблицы значення із заданим ключем

    Values

    Повертає всі значення хэш-таблицы у вигляді колекції, вміст якої перебирається в циклі For-each

    За допомогою класу Hashtable можна зберегти інформацію, отриману при виклику методу Getenvironmentvariables класу System. Environment. Приведена нижче невелика програма виводить імена і значення всіх змінних оточення, визначених в системі. Програму можна завершити у будь-який момент, просто закривши консольне вікно. Спочатку проглянете лістинг, а потім ми пояснимо пару неочевидних моментів:

    1 Option Strict On

    2 Imports System.Environment

    3 Module Modulel

    4 Sub Main()

    5 Dim evariables As Hashtable

    6 evariables =CType(Getenvironmentvariables().

    Hashtable)

    7 Console.Writel_ine("Press Enter to

    see the next item")

    8 Dim thing As Object

    9 For Each thing In evariables.Keys

    10 Console.WriteLineC'The environment

    variable named " & _

    11 thing. Tostring() & "has value " &

    evariables(thing).ToString())

    12 Console. Readline()

    13 Next

    14 End Sub

    15 End Module

    Перш за все використаний в рядку 6 спрощений синтаксис імені методу став можливим завдяки виклику Imports в рядку 2: evariables =CType(Getenvironmentvariables(),Hashtable)

    Значення, отримане при виклику Getenvironmentvariables(), перетвориться в хэш-таблицу функцією Стуре [ Можливо, в майбутніх ієрсиях .NET таке перетворення працювати не буде. ]. У рядках 8 і 9 для перебору елементів хэш-таблицы використовується змінна типу Object:

    Dim thing As Object

    For Each thing In evariables.Keys

    У стандартних хэш-таблицах зберігаються тільки об'єкти. Але оскільки в VB .NET всі дані є об'єктними, строкові значення змінних оточення також можуть зберігатися в змінній thing. Програма перебирає вміст колекції Keys і за допомогою властивості Item для кожного ключа набуває асоційованого значення. Конструкцію evariables(thing) в рядку 11 також можна записати в наступному вигляді:

    evariables.Item(thing)

    У рядку 11 викликається метод Tostring, визначений в кожному класі (цей важливий метод описаний в розділі 5). Тут цей метод використовується для виведення строкового представлення ключа.

    Об'єктні змінні

    Розглянемо наступний фрагмент:

    Dim thing As New Object

    Dim arandomlnstance As New Random

    У нім оголошуються і створюються дві змінні: thing і arandomlnstance. Перша змінна містить посилання на тип Object, а друга — посилання на екземпляр класу Random. Наступна команда цілком допустима навіть в режимі жорсткої перевірки типів (Option Strict On), оскільки в VB .NET всі змінні кінець кінцем є об'єктами:

    thing = arandomlnstance

    З іншого боку, зворотне привласнення (arandomlnstance = thing) неприпустимо, оскільки не кожен об'єкт є екземпляром класу Random.

    Об'єктну змінну можна розглядати як маніпулятор блоку пам'яті (причому не фіксованого, а переміщуваного). Об'єктні змінні також часто називають посиланнями (references) або інтелектуальними покажчиками (smart pointers). Зазвичай при використанні знаку = з ключовим словом New маніпулятор зв'язується з блоком пам'яті, в якому зберігається відповідний об'єкт (при роботі з так званими структурними типами виникають деякі тонкощі, які розглядатимуться далі в цьому розділі).

    Як буде показано в наступному розділі, загальним предком всіх типів VB .NET є тип Object. Саме тому в VB .NET будь-яку величину можна зберегти в змінній типу Object, а будь-який створений об'єкт підтримує методи класу Object. Наприклад, оскільки в класі Object визначений метод Tostring, кожен клас дозволяє отримати строкове представлення об'єкту (корисність якого залежить від реалізації). Метод Tostring автоматично викликається при використанні конструкцій виду Console. Writeline(foo).
    Якщо об'єктна змінна містить маніпулятор блоку пам'яті, в результаті операції привласнення другій об'єктній змінній буде привласнений маніпулятор того ж блоку пам'яті. Але якщо ви забудете про те, що для роботи з одним блоком пам'яті використовуються дві разниє змінні, це може привести до сумних наслідків — зміни в стані об'єкту, внесені через одну змінну, автоматично вплинуть на іншу змінну. Для прикладу розглянемо наступний фрагмент:

    Sub Maln()

    Dim A As New Arraylist()

    Dim В As Arraylist

    У = А

    B.Add("foo")

    Console.WriteLine(A.Count)

    Console.ReadLine() End Sub

    Динамічний масив А також міститиме рядок foo, тому виведене значення A.Count дорівнюватиме 1.

    Якщо ви знайомі з мовами, в яких широко використовуються покажчики (наприклад, З або Pascal), ви побачите, що у об'єктних змінних є багато загального з покажчиками. Головна відмінність полягає в тому, що разименованіє (dereferencing) об'єктних змінних відбувається автоматично і з ними не можуть виконуватися математичні операції.

    Оскільки в VB .NET рядки і масиви є об'єктами, слід пам'ятати, що для роботи з ними використовуються об'єктні змінні. Як було показано в розділі 3, це дозволяє використовувати вбудовані можливості відповідних класів за допомогою синтаксису «.». Наприклад, при роботі з масивом через змінну апаггау команда anarray.Sort() відсортує масив надзвичайно ефективним методом швидкого сортування.

    На жаль, за все хороше доводиться платити. Передача об'єктних змінних за значенням пов'язана з певними труднощами, які тепер розповсюджуються і на стандартні об'єкти на зразок масивів. Дана тема розглядається ст. розділі «Проблеми з передачею об'єктних змінних за значенням» цього розділу.

    Як і в колишніх версіях VB, об'єктні змінні можуть використовуватися для отримання компактнішого запису. Наприклад, в наступному фрагменті визначається коротке ім'я авох, яке використовуватиметься замість довгого Му-

    Form.TextBoxl:

    Dim abox As System.Windows.Forms.TextBox abox = Myform.TextBoxl

    Подібні скорочення часто використовуються у поєднанні з ключовим словом With:

    With abox

    .AutoSize =False

    .Height =1000

    .Width =200

    .Text ="Hello"

    End With

    Is і Nothing

    Оператор Is перевіряє, чи посилаються дві об'єктні змінні на одну область пам'яті. Наступний фрагмент в обох випадках виводить True, оскільки в результаті операцій привласнення всі об'єктні змінні посилаються на одну область пам'яті:

    Dim Objectl As New Object()

    Dim OBJECTZ As New Object()

    Dim Objects As New Object()

    OBJECTZ =Object1

    Objects Object2

    Console.WriteLine(Objectl Is Object2)

    Console.WriteLine(Object1 Is Object3)

    Як і в колишніх версіях VB, привласнення об'єктній змінній значення Nothi ng розриває її зв'язок з блоком пам'яті. Коли об'єктна змінна рівна Nothing, вона не асоціюється ні з яким об'єктом. У цьому стані знаходяться всі об'єктні змінні, які були оголошені в програмі, але ще не ініціалізувалися. У програмі часто зустрічаються перевірки наступного вигляду:

    If anobject Is Nothing Then

    ' Змінна не пов'язана з об'єктом, привласнити значення

    Else

    ' Значення було привласнене раніше

    End If

    Додаткова інформація про те, що відбувається при привласненні об'єктним змінним значення Nothing, приведена в розділі «Збірка сміття і завершення».

    Typename і Typeof


    Змінні, оголошені з типом Object, можуть використовуватися для зберігання довільних об'єктів. Отже, програмістові необхідні засоби для визначення типу об'єкту, пов'язаного з об'єктною змінною. У VB .NET це завдання вирішується двома способами: функцією Typename і оператором Typeof ...Is.

    Функція Typename повертає рядок з описом типу. Для всіх типів, окрім базових, має бути заздалегідь викликаний оператор New; інакше функція повертає рядок Nothing. Наприклад, наступний фрагмент виводить в консольному вікні рядок Nothing:

    Dim ansbuilder As System.Text.StringBuilder

    Console.WriteLineC'My type name is " & Typename(ansbuilder))

    Але після виклику New у вікні буде виведений рядок Stringbuilder:

    Dim ansbuilder As New System.Text.StringBuilder

    Console.WriteLineC'My type name is " & Typename(ansbuilder))

    Функція Typename повертає коротке ім'я класу, тому не розраховуйте отримати повне ім'я виду System.Text.StringBuilder.

    Якщо викликати функцію Typename для масиву, ви отримаєте строкове ім'я, за яким слідує порожня пара круглих дужок. Приклад:

    Dim athing(5) As Integer

    Console.WriteLine("My type Harness " & Typename(athing))

    Отриманий рядок має вид Integer().

    Функція Typename зручна в процесі відладки, але в остаточних версіях програм зазвичай використовується оператор Typeof...Is. Він працює набагато ефективніше, оскільки обходиться без порівнянь рядків, необхідних при використанні Typename. Синтаксис перевірки виглядає таким чином:

    If Typeof athing Is System.Text.SthngBuilder Then

    ' Об'єкт відноситься до типу Stringbuilder End If

    Оператор Typeof...Is повертає True, якщо об'єкт відноситься до заданого типу або є похідним від нього. Оскільки в .NET всі об'єкти є похідними від загального предка Object перевірка виду Typeof...Is Object завжди повертає True, навіть якщо змінна відноситься до типу, похідного від Object. Якщо вам потрібно буде дізнатися точний тип об'єктної змінної, скористайтеся методом Gettype.

    Проблеми з передачею об'єктних змінних за значенням

    Більшість мов програмування вимагають чіткого розуміння, чим передача параметрів по посиланню відрізняється від передачі за значенням. Не забувайте, що в VB .NET параметри за умовчанням передаються за значенням (Byval).

    Більшість програмістів керуються простим правилом: якщо параметр передавався по посиланню, його зміни зберігаються в початковій змінній, а якщо за значенням — зміни втрачаються після виходу з функції або процедури. На жаль, у випадку з об'єктними змінними це правило не завжди істинно. Спробуйте виконати наступний фрагмент, в якому масив передається в процедуру за значенням. Ви переконаєтеся в тому, що початковий масив змінюється після виклику процедури!

    Module Modulel Sub Main()

    Dim a() As String ={"HELLO"."GOODBYE"}

    Console.WriteLineC'Original first item in array is:" & а(0))

    Console.WriteLineC'Original second item in array is:" & а(1))

    Yikes(a)' Масив передається за значенням!

    Console.WriteLineC'After passing by value first item in array now is:"_

    &A(0))

    Console.WriteLine("After passing by value second item in array is:"_

    &АШ)

    Console. Readline()

    End Sub

    Sub Yikes(Byval Foo As String())

    Foo(0)= "GOODBYE"

    Food) = "HELLO"

    End Sub

    End Module

    Мал. 4.7. Результат роботи тестової програми

    Те, що відбувається виглядає щонайменше дивно; ми передаємо масив за значенням, але зміни чомусь відбиваються в початковій копії! У попередніх версіях VB це було б неможливо. Отже, що відбувається?

    Головна причина полягає в тому, що при передачі за значенням завжди створюється нова копія початкової змінної; після виходу з функції ця копія знищується. Але, передаючи за значенням об'єктну змінну, ви наказуєте VB .NET створити копію маніпулятора для роботи з об'єктом. Усередині процедури операції з тимчасовим маніпулятором відбиваються на вмісті цієї області пам'яті. Після виклику з процедури копія знищується, але всі зміни у вмісті пам'яті залишаються в силі.

    Уявіть собі валізу, до якої тимчасово приробили другу ручку. Ви перенесли валізу за нову ручку на інше місце; навіть якщо тепер від'єднати ручку, валіза все одно залишиться на новому місці.

    У цій дивній ситуації є лише одне виключення — коли початковий об'єкт є незмінним (immutable). Із стандартних, постійно використовуваних класів до цієї категорії відноситься тільки клас Stri ng. В цьому випадку передача за значенням працює саме так, як годиться, в чому неважко переконатися за допомогою наступної програми:

    Option Strict On Module Modulel Sub Main()

    Dim A As String = "hello"

    Noproblem(A)

    Console.WriteLine("After passing by value the string is still " & A)

    Console. Readline()

    End Sub

    Sub Noproblem(Byval Foo As String)

    Foo = "goodbye"

    End Sub

    End Module

    BVB .NET існують так звані структурні типи (value types), до яких належать звичайні числа, дати і перераховувані типи (програміст також може визначати власні структурні типи, як буде показано далі в цьому розділі). Для структурних типів передача за значенням працює цілком традиційно. Дивна ситуація, описана вище, виникає тільки при передачі за значенням змінних посилальних типів.

     




    :: Наша кнопка ::

    Отримати код:

    Підтримайте наш сайт і розмістіть нашу кнопку на своєму ресурсі.


    :: Реклама ::

    Скачати безкоштовно програму Microsoft Front Page 2003


    :: Посилання ::

    -


     

     

     


    Copyright ©