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

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


Зміст


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

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

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

 

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

Будь-який тип даних в мові програмування C# представлений класом або структурою. Відповідно усі типи даних мови C# поділяються на дві категорії (групи):

  • значимі типи або типи-значення (value-types). Типи-значення ще називають структурні типи або базові типи. Типи-значення описуються структурами;
  • посилальні типи (reference-types). Посилальні типи описуються класами.

 

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

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

  • типи-значення описуються структурами. Типи-посилання описуються класами;
  • при оголошенні змінної типу-значення екземпляр цієї змінної розміщується в стеку повністю. При оголошенні посилальної змінної, в стеку розміщується тільки посилання на екземпляр, а сам екземпляр (дані + методи) розміщується в так званій керованій “купі” (“кучі” або managed heap);
  • при присвоюванні змінної значимого типу створюється повний дублікат змінної. При присвоюванні об’єктів посилального типу копіюється тільки посилання на об’єкт, таким чином обидва посилання вказують ту саму ділянку пам’яті.

 

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.

 


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