C#. Категорії (групи) типів даних. Типи-значення. Посилальні типи. Базові типи даних. Огляд




Категорії (групи) типів даних у C#. Типи-значення. Посилальні типи. Базові типи даних. Огляд


Зміст


Пошук на інших ресурсах:

1. Що таке тип даних у мові C#?

У мові C# (та й у будь-якій іншій мові) тип даних – це є характеристика змінної (об’єкту), константи чи числового значення (літералу), яка визначає:

  • множину допустимих значень;
  • внутрішню форму представлення даних в комп’ютері (ЕОМ);
  • набір операцій, що є допустимими для цього типу.

 

2. Які категорії (групи) типів даних визначені у мові C#?

У .NET Framework будь-які типи даних (int, float, StreamReader, TextWriter та інші) представлені структурою або класом у загальній ієрархічній структурі.

У мові C# визначено дві категорії типів:

  • типи-значення або структурні або значимі типи (value types). До таких типів належать усі об’єкти структур. Усі типи-значення успадковані від базового класу System.ValueType. Прикладами типів-значень є базові типи int, double, char та інші а також їх структурні еквіваленти Int32, Double, Char тощо;
  • типи-посилання або посилальні типи (reference types). До таких типів належать усі об’єкти класів. Прикладами типів-посилань є власно-розроблені класи, класи з бібліотеки .NET чи класи інших розробників.

 

3. Які відмінності між типами-значеннями та посилальними типами?

Між типами-значення (значимими типами) та типами-посиланнями (посилальними типами) можна визначити відмінності за наступними ознаками.

1. Спосіб збереження об’єкту (змінної) типу в пам’яті комп’ютера.

Об’єкти (змінні) типів-значень розміщуються в стеку повністю. Об’єкти типів-посилань розміщуються за наступним принципом:

  • в стеку розміщується посилання на дані об’єкту;
  • в “керованій купі” (managed heap) безпосередньо розміщуються дані (поля) об’єкту. На ці дані вказує посилання зі стеку.

2. Відмінність в базовому типі.

Для значимих типів базовим типом є System.ValueType. Для посилальних типів базовим типом може бути будь-який незапечатаний (не sealed) тип крім System.ValueType.

3. Можливість бути успадкованим.

Значимі типи завжди є запечатаними, а тому не можуть бути успадкованими (бути базовими для інших). Типи-посилання можуть виступати базовими (бути успадкованими) для інших типів, якщо вони не є запечатаними (не позначені як sealed).

4. Спосіб передачі параметрів у функцію.

Змінні значимих типів передаються за значеннями. Це означає, що функції передається повна копія змінної-аргументу.
У випадку посилальних типів при передачі посилання у функцію, за значенням копіюється тільки посилання.

5. Перевизначення методу System.Object.Finalize().

Типи-значення не потребують фіналізації, оскільки ніколи не розміщуються в “керованій купі”, на відміну від посилальних типів.

6. Час існування змінної.

Типи-значення припиняють своє існування коли виходять за рамки того контексту, в якому вони визначались. Типи-посилання знищуються “збирачем сміття” (garbage collector).

Спільним для типів-значень та типів-посилань є те, що для тих і тих можна визначати конструктори.

 

4. Доцільність застосування кожної категорії типів даних

Для кожної категорії типів визначені умови їх застосування. Якщо важливим є невеликий об’єм пам’яті та швидкодія, то більш доцільно застосовувати типи-значення. Якщо для збереження даних потрібен великий об’єм пам’яті, то більш доцільно використовувати посилальні типи. Це пов’язане з тим, що розмір керованої “купи” більший за розмір стеку.

 

5. Поняття базового типу в .NET.

Базові типи – це типи-значення, які описуються структурами. У мові C# будь-якому базовому типу відповідає оголошення деякої структури, що входить у склад платформи .NET.
Наприклад. Типу float відповідає .NET структура System.Single; типу long відповідає .NET структура System.Int64.
Більш детально про використання базових типів у C# описується тут.

 

6. Структура системи базових типів у .NET

Всі вбудовані типи C# є похідними від класу Object. На рисунку відображена частина структури базової системи типів мови C#. Як видно з рисунку 1, типи-значення успадковані від класу ValueType, який успадкований від класу Object.

C#. Ієрархічна структура базових типів .NET

Рисунок 1. Загальна скорочена ієрархічна структура основних базових типів C#

 

7. Цілочисельні базові типи даних та їх .NET еквіваленти

Таблиця базових цілочисельних типів даних та структур, що відповідають цим типам, зображена рисунку 2. Відображено

  • назва типу;
  • назва .NET структури, що відповідає цьому типу;
  • ознака наявності знаку числа (від’ємні числа);
  • діапазон допустимих значень, які може приймати змінна даного типу.

 

C#. Цілочисельні базові типи даних та відповідні їм .NET структури

Рисунок 2. Цілочисельні базові типи даних та відповідні їм .NET структури

 

8. Типи даних для чисел з плаваючою комою та їх .NET еквіваленти

На рисунку 3 зображені базові типи даних для чисел з плаваючою комою та їх характеристики.

C#. Типи даних для чисел з плаваючою комою та відповідні їм .NET структури

Рисунок 3. Типи даних для чисел з плаваючою комою та відповідні їм .NET структури

 

9. Символьний тип даних char. Структура System.Char

Для представлення символьної інформації у мові C# використовується базовий тип char. У .NET цьому типу відповідає структура System.Char. Кожна змінна типу char представляє символ у форматі Unicode. У цьому форматі кожен символ ідентифікується 21-бітним скалярним значенням що називається “code point” (кодова точка). Таке представлення відповідає кодовій формі UTF-16 в якій кодова точка декодується в одне або декілька 16-бітних значень.

Структура System.Char, яка описує тип char, містить:

  • 16-бітне значення в діапазоні від 0x0000 до 0xFFFF;
  • набір методів для порівняння об’єктів типу char.

 

10. Логічний тип даних bool. Структура System.Boolean

У базовій системі типів .NET логічному типу даних bool відповідає структура System.Boolean. Змінна типу bool може приймати одне з двох значень: true (істина) або false (не істина).

 

11. Застосування операції присвоєння = для типів-значень та типів посилань

Для типів-значень та типів-посилань операція присвоєння має свої особливості. Розглянемо їх на прикладі присвоєння двох змінних.

1. Присвоєння типів-значень.

До типів-значень належать змінні базових типів (int, double, char та інші), структурні змінні (struct) та зчислення (enum). В цілому такі змінні є похідними від класу System.ValueType. При присвоюванні таких змінних

var1 = var2;

значення змінної var2 копіюється у змінну var1. Таким чином, змінна var1 містить копію змінної var2. Подальша зміна значення однієї змінної ніяк не вплине на значення іншої змінної.

2. Присвоювання типів посилань

До типів посилань належать типи, що описуються класами. При присвоюванні змінних посилального типу якими є екземпляри класів чи об’єкти,

MyClass ref1;
MyClass ref2;
...
ref1 = ref2; // присвоювання посилань
...

значення змінної-посилання ref2 копіюється в змінну-посилання ref1. У результаті обидва посилання містять адресу об’єкту, на який вказує посилання ref2. Сам об’єкт не копіюється. Таким чином, обидва посилання вказують на той самий об’єкт. При розробці програм цю особливість потрібно враховувати.

Приклад. У прикладі демонструється застосування операції присвоювання для змінних типу-значення та змінних посилального типу. Приклад реалізований для додатку типу Console Application.

using System;

namespace ConsoleApp2
{
  // Клас Integer - посилальний тип
  class Integer
  {
    public int value; // цілочисельне значення
  }

  class Program
  {
    static void Main(string[] args)
    {
      // Операція присвоювання для типів-значень
      int a, b;
      a = 8;

      // значення змінної a копіюється в змінну b
      b = a; // b = 8, a = 8
      Console.WriteLine("a = {0}, b = {1}", a, b);

      a = 6; // a = 6, b = 8 - змінні розміщені в різних ділянках пам'яті
      Console.WriteLine("a = {0}, b = {1}", a, b);

      // Операція присвоювання для типів-посилань
      // Оголосити дві змінні-посилання типу Integer
      Integer d1, d2;

      // виділити пам'ять для посилання d1
      d1 = new Integer();
      d1.value = 37; // заповнити значенням

      // виділити пам'ять для посилання d2
      d2 = new Integer();
      d2.value = 50; // заповнити значенням

      // операція присвоєння посилань - копіюються тільки посилання
      d2 = d1; // d2.value = 37
      Console.WriteLine("d1.value = {0}, d2.value = {1}", d1.value, d2.value);

      d2.value = 100; // d1.value = 100 - посилання вказують на один об'єкт
      Console.WriteLine("d1.value = {0}, d2.value = {1}", d1.value, d2.value);
    }
  }
}

Результат роботи програми

a = 8, b = 8
a = 6, b = 8
d1.value = 37, d2.value = 37
d1.value = 100, d2.value = 100

Як видно з результату, при присвоюванні посилань

d2 = d1;

обидва посилання вказують на пам’ять, виділену для об’єкту d1. Зміна значення в посиланні d2

d2.value = 100;

призводить до зміни значення в посиланні d1: d1.value = 100.

 


Зв’язані теми