Литералами называются константы, содержащие явное значение соответствующего элементарного типа, не обозначенное идентификатором. Это могут быть:
int )uint )float )double )decimal ). Длина 16 байт для уменьшения ошибок округленияtrue, True, false, False - bool )char )string )string )По сути, все
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
void |
+ | Void |
Пусто | Применяется для соблюдения синтаксиса |
sbyte |
- | SByte |
-128 - 127 | Знаковое 8 бит |
byte |
+ | Byte |
0 - 255 | Беззнаковое 8 бит |
short |
+ | Int16 |
-32'768 - 32'767 | Знаковое 16 бит |
ushort |
- | UInt16 |
0 - 65'535 | Беззнаковое 16 бит |
int |
+ | Int32 |
-2'147'483'648 - 2'147'483'647 | Знаковое 32 бит (4 байта) |
uint |
- | UInt32 |
0 - 4'294'967'295 | Беззнаковое 32 бит |
long |
+ | Int64 |
-9'223'372'036'854'775'808 - 9'223'372'036'854'775'807 | Знаковое 64 бит (8 байт) |
ulong |
- | UInt64 |
0 - 18'446'774'073'709'551'615 | Беззнаковое 64 бит (8 байт) |
char |
+ | Char |
U+0000 - U+FFFF | Для описания только одного символа Unicode 16 бит |
float |
+ | Single |
1.5x10-45 - 3.4x1038 | Знаковое с плавающей точкой 32 бит (4 байта) |
double |
+ | Double |
5.0x10-324 - 1.7x10308 | Знаковое с плавающей точкой 64 бит (8 байт) |
bool |
+ | Boolean |
true или false |
Логическое |
decimal |
+ | Decimal |
100 - 1028 | Знаковое целое (16 байт) |
string |
+ | String |
Ограничено только системной памятью | Для описания строки символов Unicode любой длины |
object |
+ | Object |
Практически все что угодно. Все типы происходят от System.Object, поэтому объектом является все |
Класс, базовый для всех типов в . NET |
Вот простая программа, характеризующая литералы и
using System;
namespace Test
{
class Program
{
static string str;// Инициализируется пустой строкой
static void Main(string[] args)
{
// Настройка консоли
Console.Title = "Литералы и элементарные типы в C#";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Печать типов
Console.WriteLine("Тип(длина) \t{Min} ~ {Max}"
+ Environment.NewLine);
str += String.Format("sbyte({0}) \t{1} ~ {2}\r\n",
sizeof(sbyte), sbyte.MinValue, sbyte.MaxValue);
str += String.Format("byte({0}) \t{1} ~ {2}\r\n",
sizeof(byte), byte.MinValue, byte.MaxValue);
str += String.Format("short({0}) \t{1} ~ {2}\r\n",
sizeof(short), short.MinValue, short.MaxValue);
str += String.Format("ushort({0}) \t{1} ~ {2}\r\n",
sizeof(ushort), ushort.MinValue, ushort.MaxValue);
str += String.Format("int({0}) \t{1} ~ {2}\r\n",
sizeof(int), int.MinValue, int.MaxValue);
str += String.Format("uint({0}) \t{1} ~ {2}\r\n",
sizeof(uint), uint.MinValue, uint.MaxValue);
str += String.Format("long({0}) \t{1} ~ {2}\r\n",
sizeof(long), long.MinValue, long.MaxValue);
str += String.Format("ulong({0}) \t{1} ~ {2}\r\n",
sizeof(ulong), ulong.MinValue, ulong.MaxValue);
str += String.Format("char({0}) \t{1:X} ~ {2:X}\r\n",
sizeof(char), (int)char.MinValue, (int)char.MaxValue);
str += String.Format("float({0}) \t{1} ~ {2}\r\n",
sizeof(float), float.MinValue, float.MaxValue);
str += String.Format("double({0}) \t{1} ~ {2}\r\n",
sizeof(double), double.MinValue, double.MaxValue);
str += String.Format("decimal({0}) \t{1} ~ {2}\r\n",
sizeof(decimal), decimal.MinValue, decimal.MaxValue);
Console.WriteLine(str);
Console.ReadLine();
}
}
}
Рузультат выполнения будет таким
В строковых литералах применяются управляющие последовательности.
Строковый литерал можно сделать буквальным ( verbatim - дословный), если перед открывающей кавычкой поставить символ @. Содержимое строки не интерпретируется и может быть многострочным. Но если внутри строкового литерала используется символ ", то его нужно заэкранировать таким же символом. Управляющие символы в такой строке не действуют.
using System;
namespace Test
{
class Program
{
static void Main(string[] args)
{
// Настройка консоли
Console.Title = "Буквальный строковый литерал";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Буквальный строковый литерал
string str;// Локальная переменная не инициализируется
str =
@"Привет всем от \n
Иванова
Петрова
Сидорова
""Фантомаса""
\t...............
и от многих других";
Console.WriteLine(str);
Console.ReadLine();
}
}
}

С литералами можно обращаться как с переменными соответствующих типов (не забывая, что это константы), например, приводить литерал к другому типу или использовать методы типов, наследуемые от ValueType/Object. При приведении типа литерала к родственному типу переменной соблюдаются те же правила, что и при приведении типов переменных. Если тип переменной имеет количество байт для хранения ее значений, способный уместить максимальное значение литерала без потери данных, то его можно приводить неявно. В противном случае нужно указать оператор явного приведения типов.
using System;
namespace Test
{
class Program
{
static void Main()
{
// Настройка консоли
Console.Title = "Приведение простых типов";
Console.ForegroundColor = ConsoleColor.White;
double a = 11.1f;// Неявное приведение малого к большому
float b = (float)11.1d; // Явное приведение большого к малому
float c = (int)11;// Неявное приведение целого к вещественному
long d = (short)11; // Неявное приведение короткого к длинному
string str = "";// Локальная переменная
str += a.ToString() + "\t"
+ b.ToString() + "\t"
+ c.ToString() + "\t"
+ d.ToString() + Environment.NewLine
// Литералы - те же простые типы
// и имеют соответствующие методы
+ (11.1f).ToString() + "\t"
+ (11.1d).ToString() + "\t"
+ (11).ToString() + "\t"
+ ((short)11.1f).ToString();
Console.WriteLine(str);
Console.WriteLine("\nВведите вещественное число");
Console.Write("(дробная часть через запятую): ");
str = Console.ReadLine();
try
{
float f = Convert.ToSingle(str);// Преобразование к float
Console.WriteLine("Вы ввели число: {0}", f);
int x = (int)f;
float y = f - x;
Console.WriteLine("\nЦелая часть числа: {0}", x);
Console.WriteLine("Дробная часть числа: {0}", y);
}
catch
{
Console.WriteLine("Вы ввели не число");
}
Console.ReadLine();
}
}
}
Экземпляры классов создаются методами налету в управляемой куче, а ссылки на них размещаются в стеке потока. Такие типы называются ссылочными, поскольку в программе представлены не самими данными, а ссылками на них. Их экземпляры еще называют неименованными данными. С другой стороны, простые (
При работе метода все его локальные переменные помещаются в стек потока. Если локальная переменная, помещенная в стек, представляет ссылочный тип, то сами данные находятся в управляемой куче в области размещения объекта-экземпляра. Если локальная переменная представляет
Объекты
int x; Point point;) int x = new int(); Point point = new Point(); )Динамическое объявление значимого типа предполагает одновременно создание и инициализацию объекта. Поэтому его допустимо применять и внутри метода. Статическое объявление предполагает неявный вызов конструктора по умолчанию только при объявлении полей класса. В этом случае допустимо применять как статическое, так и динамическое объявление с явным вызовом конструктора по умолчанию или пользовательского конструктора.
Объявление значимых переменных сложных типов внутри метода требует явного вызова конструктора, поскольку неявная инициализация не производится. Простые значимые типы, поскольку они имеют только одно общедоступное значение, внутри метода допустимо вначале объявлять, а затем инициализировать литералом. Чтобы применить статическое объявление к сложному
Когда выполняется присваивание совместимых объектов
В значимых типах конструктор по умолчанию зарезервирован и его перегружать нельзя, даже если определены пользовательские конструкторы. В ссылочном типе - классе конструктор без параметров нужно обязательно перегрузить, если его предполагается использовать вместе с добавленными параметризованными конструкторами.
using System;
namespace Test
{
class Program
{
static void Main()
{
new Some();
Console.ReadLine();
}
}
struct Point
{
int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public void Show()
{
Console.WriteLine("x={0}; y={1}", x, y);
}
}
class Some
{
//Point point;
public Some()
{
Point point = new Point();
point.Show();
}
}
}
Иногда может потребоваться хранить object, поскольку класс object является порождающим для всех типов C#. Такой процесс называется упаковкой значимого объекта. Синтаксис упаковки такой
object refValue = point;
Среда выполнения сама зарезервирует место в динамической области памяти и скопирует туда все данные
Упакованный объект можно передать как ссылочный параметр любому внешнему методу. Обратный процесс получения значимого объекта по его ссылке называется распаковкой. По ссылке упакованного объекта нельзя обратиться к его членам. Для этого объект нужно распаковать. Синтаксис распаковки такой
Point point = (Point)refValue;
Ссылка на упакованный объект приводится с помощью явного преобразования к самому объекту того же типа. Типы упакованного и распакованного объектов должны быть совместимы, т.е. иметь одинаковую структуру данных и функций (из чего упаковали, в то и распаковываем).
Экземпляр класса (объект), размещенный при выполнении метода в управляемой куче и адресуемый в программе по ссылке, называется упакованным. Структура или перечисление, размещаемые при выполнении метода в стеке потока, называются распакованными. Здесь речь идет только о членах-данных этих программных единиц.
Поскольку структуры производятся от класса Systcode.ValueType, который, в свою очередь произошел от класса Systcode.Object, то Systcode.Object. Такая процедура называется упаковкой.
И наоборот, если есть ссылка на упакованный
using System;
namespace Test
{
struct Point
{
// Поля
public int x, y;
// Конструктор
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Функция доступа
public void Set(int x, int y)
{
this.x = x;
this.y = y;
}
// Печать
public void Show(string message)
{
Console.WriteLine(message + "x={0}, y={1}", x, y);
}
}
// Класс с функцией Main не может иметь экземпляр
// Поэтому все функции в этом классе должны быть статическими
class EntryPoint
{
static Point valPoint3; // Поле в объекте-типе
static void Main(string[] args)
{
// Настройка консоли
Console.Title = "";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Point valPoint = new Point(5, 10);// Инициализировали и поместили в стек
valPoint.Show("Исходный объект в стеке: ");
object refPoint = valPoint;// Упаковка: ссылка в стеке, объект в куче
((Point)refPoint).Show("\nИсходный объект в куче: ");
object refPoint1 = refPoint;// Еще одна ссылка на объект в куче
CreatePackPoint(ref refPoint1);// Создали еще один объект в куче
((Point)refPoint1).Show("\nНовый объект в куче: ");
Point valPoint1 = new Point();
valPoint1.Show("\nЕще один локальный объект в стеке: ");
Point valPoint2;// Статическое объявление локального объекта
valPoint2.x = 50;// Обязательная инициализация
valPoint2.y = 70;// Обязательная инициализация
valPoint2.Show("\nИ еще один локальный объект в стеке: ");
valPoint3.Show("\nОбъект-поле в типе: ");
Console.ReadLine();// Для задержки окна
}
static void CreatePackPoint(ref object arg)
{
Point point = (Point)arg;// Распаковываем
point.Set(20, 30);// Изменяем
arg = point;//Опять упаковываем
}
}
}
Процесс упаковки выполняется автоматически при передачи объекта методу в случае, если метод ожидает упакованный объект, а ему в качестве аргумента передается распакованный объект.
using System;
namespace Test
{
// Значимый тип, данные размещаются в стеке
struct Point
{
// Закрытые поля
int x, y;
// Конструктор
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Функция доступа
public void Set(int x, int y)
{
this.x = x;
this.y = y;
}
// Печать
public void Show(string message)
{
Console.WriteLine(message + "x={0}, y={1}", x, y);
}
}
// Класс с функцией Main может иметь экземпляр
// Необязательно все функции в этом классе должны быть статическими
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Автоматическая упаковка аргумента метода";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Point valPoint = new Point(5, 10);// Инициализировали и поместили в стек
valPoint.Show("Распакованный объект вне метода: ");
Program prg = new Program();//!!!!!
prg.AutoPackPoint(valPoint);// Создали еще один объект в куче
valPoint.Show("Распакованный объект вне метода: ");
Console.ReadLine();// Для задержки окна
}
// Метод ожидает упакованный объект, поэтому
// автоматически упаковывает распакованный аргумент
void AutoPackPoint(object arg)
{
// Проверим тип для подстраховки, чтобы не вызвать исключение
if (arg is Point)
{
Point point = (Point)arg;// Распаковываем
point.Set(20, 30);// Изменяем
point.Show("Распакованный объект внутри метода: "); // Печатаем
}
else
Console.WriteLine("Вы прислали не Point!");
}
}
}

Если метод ожидает сам значимый объект, то ссылку на объект передавать нельзя и ее нужно вручную распаковать.
using System;
namespace Test
{
// Класс с функцией Main не может иметь экземпляр
// Поэтому все функции в этом классе должны быть статическими
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Распаковка аргумента метода вручную";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Point valPoint = new Point(5, 10);// Инициализировали и поместили в стек
valPoint.Show("Распакованный объект вне метода: ");
object refPoint = valPoint;// Упаковали значимый объект
ManualUnPackPoint((Point)refPoint);// Распаковываем вручную
Console.ReadLine();// Для задержки окна
}
// Метод ожидает распакованный объект, распаковка
// должна выполняться вручную для контроля типов
static void ManualUnPackPoint(Point arg)
{
arg.Set(20, 30);// Изменяем распакованную копию
arg.Show("Копия объекта внутри метода: "); // Печатаем
}
}
}
namespace Test
{
// Значимый тип, данные размещаются в стеке
struct Point
{
// Закрытые поля
int x, y;
// Конструктор
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Функция доступа
public void Set(int x, int y)
{
this.x = x;
this.y = y;
}
// Печать
public void Show(string message)
{
Console.WriteLine(message + "x={0}, y={1}", x, y);
}
}
}
Перечисления ( enumerations ) относятся к Int32.
модификатор_доступа enum имя_типа{список_членов}
Список членов представляет собой список идентификаторов, разделенных запятыми. internal - в пределах сборки. Для использования во внешней сборке нужно объявлять public (как и классы).
using System;
namespace Test
{
// Значимый тип, данные размещаются в стеке
enum Fruit // Фрукты
{
Apples, // Яблоки
Plums, // Сливы
Cherries, // Вишни
Grapes, // Виноград
Pears // Груши
}
// Класс с функцией Main не может иметь экземпляр
// Поэтому все функции в этом классе должны быть статическими
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Использование перечислений";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
string[] colorFruit = { // Массив цветов
"Красный",
"Синий",
"Вишневый",
"Зеленый",
"Черный"
};
string[] nameFruit = { // Массив имен
"Яблоки",
"Сливы",
"Вишни",
"Виноград",
"Груши"
};
// Объявляем переменную перечислимого типа
Fruit fruit;
// Используем переменную перечисления для обхода всех членов
for (fruit = Fruit.Apples; fruit <= Fruit.Pears; fruit++)
Console.WriteLine(fruit + " имеет
значение " + (int)fruit);
// Используем переменную перечисления для индексации массива
Console.WriteLine();// Прогон строки
for (fruit = Fruit.Apples; fruit <= Fruit.Pears; fruit++)
Console.WriteLine("Цвет фрукта " + fruit
+ " (" + nameFruit[(int)fruit] +
") - " + colorFruit[(int)fruit]);
Console.ReadLine();// Для задержки окна
}
}
}

Значения списка перечислений по умолчанию начинаются с нуля. Но любому члену списка можно явно присвоить значение, тогда для всех последующих членов списка начнется новая точка отсчета значений натурального ряда чисел.
enum Fruit // Фрукты
{
Apples, // = 0
Plums, // = 1
Cherries = 100,
Grapes, // = 101
Pears // = 102
}
Элементы перечисления можно инициализировать в любой последовательности, закрепляя за
enum Fruit // Фрукты
{
Apples = 21,
Plums = 101,
Cherries = 100,
Grapes = 12,
//Grapes = 3,
Pears = 12
}
Элементы перечисления, как Int3 2 и занимает 4 байта. Ситуацию можно изменить, задав другой byte ) для всех элементов перечисления по следующему синтаксису
enum Fruit : byte // Фрукты
{
Apples = 21,
Plums = 101,
Cherries = 100,
Grapes = 12,
Pears = 2
}
using System;
namespace Test
{
enum Fruit // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
enum Fruit1 : byte // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
enum Fruit2 : long // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Использование перечислений";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Console.WriteLine("Члены Fruit имеют размер по "
+ sizeof(Fruit) + " байта");
Console.WriteLine("Члены Fruit1 имеют размер по "
+ sizeof(Fruit1) + " байту");
Console.WriteLine("Члены Fruit2 имеют размер по "
+ sizeof(Fruit2) + " байт");
Console.ReadLine();// Для задержки окна
}
}
}
Перечисления могут быть и членами класса
using System;
namespace Test
{
class EntryPoint
{
enum Fruit // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
static void Main()
{
// Настройка консоли
Console.Title = "Использование перечислений";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Объявляем переменную перечислимого типа
Fruit fruit;
// Используем переменную перечисления для обхода всех членов
for (fruit = Fruit.Apples; fruit <= Fruit.Pears; fruit++)
Console.WriteLine(fruit + " имеет
значение " + (int)fruit);
Console.ReadLine();// Для задержки окна
}
}
}

Приведенные способы применения перечислений встречаются очень редко, чаще используется прямое назначение перечислений как набора именованных целочисленных констант, упакованных в одном блоке кода. Библиотека .NET Framework содержит множество полезных перечислений, облегчающих программисту жизнь. Одно из таких перечислений System.Windows.Forms.Keys, содержащееся в одноименной библиотечной сборке System.Windows.Forms.dll.
using System;
using System.Windows.Forms;
using System.Drawing;
// Подключить через оболочку соответствующие сборки!!!!!!!!!!!
namespace Test
{
class MyClass : Form
{
// Сообщение в окне
string messageKey = "Нажимайте клавиши";
public MyClass() // Конструктор формы
{
// Настройка формы
try // Безопасный код загрузки иконки
{
this.Icon = new Icon("1.ICO");
}
catch { /* На исключения не реагировать */ }
this.Text = "Перечисление Keys";
this.Font = new Font("Arial", 14, FontStyle.Bold);
}
// Перегрузка метода OnPaint(), наследуемого от класса Control
protected override void OnPaint(PaintEventArgs e)
{
Form frm = this;
Graphics gr = e.Graphics;// Контекст экрана
// Создаем и настраиваем точку привязки текстового блока
StringFormat strfrm = new StringFormat();
strfrm.Alignment = StringAlignment.Center;// Центр по горизонтали
strfrm.LineAlignment = StringAlignment.Center;// Центр по вертикали
// Точка привязки на форме
PointF point = new PointF(frm.ClientSize.Width / 2,
frm.ClientSize.Height / 2);
// Выводим содержимое строки поля класса
gr.DrawString(messageKey,
frm.Font, // Применяется шрифт окна
new SolidBrush(Color.Red), // Цвет шрифта
point, // Точка привязки на форме
strfrm); // Передаем точку привязки текстового блока
// Выполняем обработчик события до полной глубины наследования
base.OnPaint(e);
}
// Перегрузка метода OnKeyUp(), наследуемого от класса Control
protected override void OnKeyUp(KeyEventArgs e)
{
// Временно сохраняем подсказку
string mess = messageKey;
// Анализируем нажатую клавишу
switch (e.KeyCode)
{
case Keys.X:
case Keys.Enter:
case Keys.Escape:
messageKey = "Нажата клавиша " + e.KeyCode
+ "\nAscii-код клавиши " + (byte)(e.KeyCode)
+ "\nЧто-то делаем...";
break;
case Keys.Space:
messageKey = "Нажата клавиша " + Keys.Space
+ "\nAscii-код клавиши " + (byte)(Keys.Space)
+ "\nЧто-то делаем...";
break;
default:
messageKey = "Нажата " + e.KeyCode
+ "\nAscii-код клавиши " + (byte)(e.KeyCode)
+ "\nОна нам не нужна!";
break;
}
// Инициируем немедленную перерисовку формы
// для вывода нового сообщения
this.Refresh();
//this.Invalidate(); // Удаляется из очереди при задержке потока
// Усыпляем текущий поток на две секунды
System.Threading.Thread.Sleep(2000);
// Восстанавливаем подсказку
messageKey = mess;
// Инициируем перерисовку формы
// для вывода восстановленной подсказки
this.Invalidate();
// Выполняем обработчик события до полной глубины наследования
base.OnKeyUp(e);
}
}
}
namespace Test
{
class EntryPoint
{
static void Main()
{
// Настройка стиля формы
Application.EnableVisualStyles();
// Цикл сообщений Windows
Application.Run(new MyClass());
}
}
}
Как только в приложении объявляется перечисление, тем самым неявно объявляется тип, производный от абстрактного класса System.Enum. Например, даже вот такой пустой код
internal enum MyEnum
{
}
internal class EntryPoint
{
static void Main()
{
}
}
дает следующую диаграмму в панели Class View оболочки

Базовый класс System.Enum является абстрактным, поэтому не может напрямую иметь экземпляры (объекты), а может использоваться только как базовый в цепочке наследования. Тем не менее он определяет ряд статических методов, позволяющих обрабатывать созданные перечисления. Вот некоторые из этих методов.
| Метод | Описание |
|---|---|
public static string Format(System.Type enumType, object value, string format) |
Преобразует значение данного типа перечисления в эквивалентное строковое представление в соответствии с указанным форматом |
public static string GetName(System.Type enumType, object value) |
Возвращает имя для константы с указанным значением |
public static string[] GetNames(System.Type enumType) |
Возвращает массив имен для константы с указанным значением |
public static System.Type GetUnderlyingType(System.Type enumType) |
Возвращает численный тип данных, используемый для хранения значений данного перечисления |
public static System.Array GetValues(System.Type enumType) |
Возвращает массив элементов указанного перечисления |
public static bool IsDefined(System.Type enumType, object value) |
Возвращает флаг существования в указанном перечислении заданного элемента |
public |
Упаковывает в объектную ссылку один или несколько элементов перечисления по их именам, заданным в строке |
public |
Упаковывает в объектную ссылку один или несколько элементов перечисления по их именам, заданным в строке |
Приведем пример программы, использующей статические методы класса System.Enum.
using System;
namespace CHETKOB.Test
{
internal enum Fruit // Фрукты
{
Apples = 102, // Яблоки
Plums = 12, // Сливы
Cherries = 50, // Вишни
Grapes = 11, // Виноград
Pears = 211 // Груши
}
internal class MyClass
{
static void Main()
{
// Настройка консоли
Console.Title = "Методы библиотечного класса Enum";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Анализируем перечисление Fruit
Array fruitArray = Enum.GetValues(typeof(Fruit));
Console.WriteLine("Определяем количество
членов перечисления:");
Console.WriteLine("Перечисление содержит {0}
членов", fruitArray.Length);
// Обходим все члены перечисления
// и выводим пары "ключ-значение"
Console.WriteLine("\nВыводим элементы перечисления:");
foreach (Fruit fruit in fruitArray)
{
Console.Write("{0, -8} = {1, -3} ",// Количество знакомест
fruit.ToString(),
Enum.Format(typeof(Fruit), fruit, "D")); // Decimal - десятичный
Console.WriteLine("(= 0x{0})",
Enum.Format(typeof(Fruit), fruit, "X"));// Hex - шестнадцатиричный
}
// Ищем элемент по значению
Console.WriteLine();
Console.WriteLine("Ищем элемент по значению:");
foreach (Fruit fruit in fruitArray)
{
int value = (int)fruit;
Console.WriteLine("Значение {0, -3}
имеет элемент {1}", value,
Enum.GetName(typeof(Fruit), value));
}
// Проверяем, есть ли элемент в указанном перечислении
Console.WriteLine();
Console.WriteLine("Проверяем существование
элемента в перечислении:");
string element = "Apples";
if (Enum.IsDefined(typeof(Fruit), element))
Console.WriteLine("Элемент {0} в
перечислении есть", element);
else
Console.WriteLine("Элемента {0} в
перечислении нет", element);
// Печатаем еще одно перечисление
Console.WriteLine();
Console.WriteLine("Печатаем еще одно перечисление:");
Type weekdays = typeof(Days);
foreach (string str in Enum.GetNames(weekdays))
Console.WriteLine("{0,-11} = {1}",
str,// Резервирует 11 знакомест
Enum.Format(weekdays, Enum.Parse(weekdays, str), "d"));
Console.ReadLine();
}
// Перечисление в классе. Доступ из других класов
// сборки будет составным: MyClass.Days
internal enum Days
{
Понедельник, Вторник, Среда, Четверг,
Пятница, Суббота, Воскресенье
};
}
}
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
sbyte |
- | SByte |
-128 - 127 | Знаковое 8 бит |
byte |
+ | Byte |
0 - 255 | Беззнаковое 8 бит |
short |
+ | Int16 |
-32'768 - 32'767 | Знаковое 16 бит |
ushort |
- | UInt16 |
0 - 65'535 | Беззнаковое 16 бит |
int |
+ | Int32 |
-2'147'483'648 - 2'147'483'647 | Знаковое 32 бит |
uint |
- | UInt32 |
0 - 4'294'967'295 | Беззнаковое 32 бит |
long |
+ | Int64 |
-9'223'372'036'854'775'808 - 9'223'372'036'854'775'807 | Знаковое 64 бит |
ulong |
- | UInt64 |
0 - 18'446'774'073'709'551'615 | Беззнаковое 64 бит |
Префикс s означает " signed " - знаковый; u - " unsigned " - беззнаковый
Наибольшее распространение имеет тип int, поскольку его диапазона значений вполне хватает для вспомогательных операций.
using System;
namespace Test
{
class Inches
{
static void Main()
{
long inches;
long miles = 93000000; // Миль до Солнца
// 5280 футов в миле, 12 дюймов в футе
inches = miles * 5280 * 12;
Console.WriteLine("Расстояние до Солнца: "
+ inches
+ " дюймов.");
Console.Read();
}
}
}
Тип byte предназначен для хранения чисел без знака от 0 до 255 размером 8 битов и полезен при обработке двоичных данных.
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
sbyte |
- | SByte |
-128 - 127 | Знаковое 8 бит |
byte |
+ | Byte |
0 - 255 | Беззнаковое 8 бит |
using System;
namespace Test
{
class UseByte
{
static void Main()
{
byte x;
int sum = 0;
for(x = 1; x <= 100; x++)
sum += x;
Console.WriteLine("Сумма чисел от
1 до 100 равна " + sum);
Console.Read();
}
}
}
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
float |
+ | Single |
1.5x10-45 - 3.4x1038 | Знаковое с плавающей точкой 32 бит |
double |
+ | Double |
5.0x10-324 - 1.7x10308 | Знаковое с плавающей точкой 64 бит |
Чаще всего используется тип double, поскольку он поддерживается множеством математических функций библиотеки .NET Framework. Большинство математических функций сосредоточено в классе System.Math
using System;
namespace Test
{
// Нахождение радиуса круга по его площади
class FindRadius
{
static void Main()
{
double radius, area = 10.0;
radius = Math.Sqrt(area / Math.PI);
Console.WriteLine("Площадь круга:
{0};", area);
Console.WriteLine("Радиус круга:
{0};", radius);
Console.Read();
}
}
}
using System;
namespace Test
{
// Использование тригонометрических методов
class Trigonometry
{
static void Main()
{
for(int i = 0; i < 3; i++) // Внешний цикл
{
// alpha - угол в градусах
for(double alpha = 0D; alpha <= 180; alpha = alpha + 10)
{
switch(i + 1)
{
case 1: Console.WriteLine("Sin({0})={1}",
alpha, Math.Sin(alpha / 180 * Math.PI));
break;
case 2: Console.WriteLine("Cos({0})={1}",
alpha, Math.Cos(alpha / 180 * Math.PI));
break;
case 3: Console.WriteLine("Tan({0})={1}",
alpha, Math.Tan(alpha / 180 * Math.PI));
break;
}
}
Console.WriteLine();
}
Console.Read();
}
}
}
Предназначен для выполнения вычислений, связанных с денежными единицами.
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
decimal |
+ | Decimal |
10-28 —1028 | Знаковое 128 бит |
Применение обычной арифметики с плавающей точкой чревато ошибками округления. Во избежании этих ошибок и предназначен тип decimal.
using System;
namespace Test
{
// Использование типа decimal для вычисления скидки
class UseDecimal
{
static void Main()
{
decimal price; // Цена
decimal discount; // Скидка
decimal discounted_price; // Цена со скидкой
// Вычисляем цену со скидкой
price = 19.95M; // Цена товара
discount = 0.15m; // Ставка дисконта равна 15%
discounted_price = price - (price * discount);// Скобки не обязательны
Console.WriteLine("Цена со скидкой: $"
+ discounted_price);
Console.Read();
}
}
}
using System;
namespace Test
{
/*
* Использование типа decimal для вычисления
* будущей стоимости капиталовложений
*/
class UseDecimal
{
static void Main()
{
decimal amount; // Исходный вклад
decimal rate_of_return; // Норма прибыли
int years; // Количество лет
amount = 1000M;
rate_of_return = .07m;
years = 10;
Console.WriteLine("Исходный вклад:
$" + amount);
Console.WriteLine("Норма прибыли:
" + rate_of_return);
Console.Write("Через " + years +
" лет будет $");
for(int i = 0; i < years; i++)
amount += amount * rate_of_return;
Console.WriteLine(amount);
Console.Read();
}
}
}
В C# исмволы представлются не в однобайтном коде ASCII, а в двухбайтном коде Unicode. Это позволяет представлять алфавиты всех существующих в мире языков. Это 16 - разрядный тип без знака.
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
char |
+ | Char |
U+0000 - U+FFFF | Для описания только одного символа Unicode 16 бит |
Символьной переменной можно присвоить значение, заключив соответствующий символ в одинарные кавычки. Например
char ch; ch = 'X';
using System;
namespace Test
{
class UseDecimal
{
static void Main()
{
char ch0 = 'П', ch1 = 'р',
ch2 = 'и', ch3 = 'в',
ch4 = 'е', ch5 = 'т';
Console.WriteLine((int)ch0);
Console.WriteLine((int)ch1);
Console.WriteLine((int)ch2);
Console.WriteLine((int)ch3);
Console.WriteLine((int)ch4);
Console.WriteLine((int)ch5 + "\n");
Console.WriteLine(ch0 + ch1 + ch2 + ch3 + ch4 + ch5);
Console.WriteLine();
Console.WriteLine(ch0);
Console.WriteLine(ch1);
Console.WriteLine(ch2);
Console.WriteLine(ch3);
Console.WriteLine(ch4);
Console.WriteLine(ch5 + "\n");
Console.WriteLine("{0}{1}{2}{3}{4}{5}\n",
ch0, ch1, ch2, ch3, ch4, ch5);
string str = Convert.ToString(ch0)
+ Convert.ToString(ch1)
+ Convert.ToString(ch2)
+ Convert.ToString(ch3)
+ Convert.ToString(ch4)
+ Convert.ToString(ch5);
Console.WriteLine(str);
Console.Read();
}
}
}
Тип bool в C# представляет логические значения true или false ( ИСТИНА/ЛОЖЬ ), которые можно использовать в операторах управления (условия, циклы).
using System;
namespace Test
{
class UseBool
{
static void Main()
{
bool logical;
logical = false;
int i;
for(i = 0; i < 2; i++)
{
logical = !logical;
Console.Write("logical={0}: ", logical);
if(logical)
Console.WriteLine("Привет от Иванова!");
else
Console.WriteLine("Привет от Петрова!");
}
Console.WriteLine("10 > 9 равно " + (10 > 9));
Console.Read();
}
}
}
Литералами называются константы, содержащие явное значение соответствующего элементарного типа, не обозначенное идентификатором. Это могут быть:
int )uint )float )double )decimal ). Длина 16 байт для уменьшения ошибок округленияtrue, True, false, False - bool )char )string )string )По сути, все
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
void |
+ | Void |
Пусто | Применяется для соблюдения синтаксиса |
sbyte |
- | SByte |
-128 - 127 | Знаковое 8 бит |
byte |
+ | Byte |
0 - 255 | Беззнаковое 8 бит |
short |
+ | Int16 |
-32'768 - 32'767 | Знаковое 16 бит |
ushort |
- | UInt16 |
0 - 65'535 | Беззнаковое 16 бит |
int |
+ | Int32 |
-2'147'483'648 - 2'147'483'647 | Знаковое 32 бит (4 байта) |
uint |
- | UInt32 |
0 - 4'294'967'295 | Беззнаковое 32 бит |
long |
+ | Int64 |
-9'223'372'036'854'775'808 - 9'223'372'036'854'775'807 | Знаковое 64 бит (8 байт) |
ulong |
- | UInt64 |
0 - 18'446'774'073'709'551'615 | Беззнаковое 64 бит (8 байт) |
char |
+ | Char |
U+0000 - U+FFFF | Для описания только одного символа Unicode 16 бит |
float |
+ | Single |
1.5x10-45 - 3.4x1038 | Знаковое с плавающей точкой 32 бит (4 байта) |
double |
+ | Double |
5.0x10-324 - 1.7x10308 | Знаковое с плавающей точкой 64 бит (8 байт) |
bool |
+ | Boolean |
true или false |
Логическое |
decimal |
+ | Decimal |
100 - 1028 | Знаковое целое (16 байт) |
string |
+ | String |
Ограничено только системной памятью | Для описания строки символов Unicode любой длины |
object |
+ | Object |
Практически все что угодно. Все типы происходят от System.Object, поэтому объектом является все |
Класс, базовый для всех типов в . NET |
Вот простая программа, характеризующая литералы и
using System;
namespace Test
{
class Program
{
static string str;// Инициализируется пустой строкой
static void Main(string[] args)
{
// Настройка консоли
Console.Title = "Литералы и элементарные типы в C#";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Печать типов
Console.WriteLine("Тип(длина) \t{Min} ~ {Max}"
+ Environment.NewLine);
str += String.Format("sbyte({0}) \t{1} ~ {2}\r\n",
sizeof(sbyte), sbyte.MinValue, sbyte.MaxValue);
str += String.Format("byte({0}) \t{1} ~ {2}\r\n",
sizeof(byte), byte.MinValue, byte.MaxValue);
str += String.Format("short({0}) \t{1} ~ {2}\r\n",
sizeof(short), short.MinValue, short.MaxValue);
str += String.Format("ushort({0}) \t{1} ~ {2}\r\n",
sizeof(ushort), ushort.MinValue, ushort.MaxValue);
str += String.Format("int({0}) \t{1} ~ {2}\r\n",
sizeof(int), int.MinValue, int.MaxValue);
str += String.Format("uint({0}) \t{1} ~ {2}\r\n",
sizeof(uint), uint.MinValue, uint.MaxValue);
str += String.Format("long({0}) \t{1} ~ {2}\r\n",
sizeof(long), long.MinValue, long.MaxValue);
str += String.Format("ulong({0}) \t{1} ~ {2}\r\n",
sizeof(ulong), ulong.MinValue, ulong.MaxValue);
str += String.Format("char({0}) \t{1:X} ~ {2:X}\r\n",
sizeof(char), (int)char.MinValue, (int)char.MaxValue);
str += String.Format("float({0}) \t{1} ~ {2}\r\n",
sizeof(float), float.MinValue, float.MaxValue);
str += String.Format("double({0}) \t{1} ~ {2}\r\n",
sizeof(double), double.MinValue, double.MaxValue);
str += String.Format("decimal({0}) \t{1} ~ {2}\r\n",
sizeof(decimal), decimal.MinValue, decimal.MaxValue);
Console.WriteLine(str);
Console.ReadLine();
}
}
}
Рузультат выполнения будет таким

В строковых литералах применяются управляющие последовательности.
Строковый литерал можно сделать буквальным ( verbatim - дословный), если перед открывающей кавычкой поставить символ @. Содержимое строки не интерпретируется и может быть многострочным. Но если внутри строкового литерала используется символ ", то его нужно заэкранировать таким же символом. Управляющие символы в такой строке не действуют.
using System;
namespace Test
{
class Program
{
static void Main(string[] args)
{
// Настройка консоли
Console.Title = "Буквальный строковый литерал";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Буквальный строковый литерал
string str;// Локальная переменная не инициализируется
str =
@"Привет всем от \n
Иванова
Петрова
Сидорова
""Фантомаса""
\t...............
и от многих других";
Console.WriteLine(str);
Console.ReadLine();
}
}
}

С литералами можно обращаться как с переменными соответствующих типов (не забывая, что это константы), например, приводить литерал к другому типу или использовать методы типов, наследуемые от ValueType/Object. При приведении типа литерала к родственному типу переменной соблюдаются те же правила, что и при приведении типов переменных. Если тип переменной имеет количество байт для хранения ее значений, способный уместить максимальное значение литерала без потери данных, то его можно приводить неявно. В противном случае нужно указать оператор явного приведения типов.
using System;
namespace Test
{
class Program
{
static void Main()
{
// Настройка консоли
Console.Title = "Приведение простых типов";
Console.ForegroundColor = ConsoleColor.White;
double a = 11.1f;// Неявное приведение малого к большому
float b = (float)11.1d; // Явное приведение большого к малому
float c = (int)11;// Неявное приведение целого к вещественному
long d = (short)11; // Неявное приведение короткого к длинному
string str = "";// Локальная переменная
str += a.ToString() + "\t"
+ b.ToString() + "\t"
+ c.ToString() + "\t"
+ d.ToString() + Environment.NewLine
// Литералы - те же простые типы
// и имеют соответствующие методы
+ (11.1f).ToString() + "\t"
+ (11.1d).ToString() + "\t"
+ (11).ToString() + "\t"
+ ((short)11.1f).ToString();
Console.WriteLine(str);
Console.WriteLine("\nВведите вещественное число");
Console.Write("(дробная часть через запятую): ");
str = Console.ReadLine();
try
{
float f = Convert.ToSingle(str);// Преобразование к float
Console.WriteLine("Вы ввели число: {0}", f);
int x = (int)f;
float y = f - x;
Console.WriteLine("\nЦелая часть числа: {0}", x);
Console.WriteLine("Дробная часть числа: {0}", y);
}
catch
{
Console.WriteLine("Вы ввели не число");
}
Console.ReadLine();
}
}
}

Экземпляры классов создаются методами налету в управляемой куче, а ссылки на них размещаются в стеке потока. Такие типы называются ссылочными, поскольку в программе представлены не самими данными, а ссылками на них. Их экземпляры еще называют неименованными данными. С другой стороны, простые (
При работе метода все его локальные переменные помещаются в стек потока. Если локальная переменная, помещенная в стек, представляет ссылочный тип, то сами данные находятся в управляемой куче в области размещения объекта-экземпляра. Если локальная переменная представляет
Объекты
int x; Point point;) int x = new int(); Point point = new Point(); )Динамическое объявление значимого типа предполагает одновременно создание и инициализацию объекта. Поэтому его допустимо применять и внутри метода. Статическое объявление предполагает неявный вызов конструктора по умолчанию только при объявлении полей класса. В этом случае допустимо применять как статическое, так и динамическое объявление с явным вызовом конструктора по умолчанию или пользовательского конструктора.
Объявление значимых переменных сложных типов внутри метода требует явного вызова конструктора, поскольку неявная инициализация не производится. Простые значимые типы, поскольку они имеют только одно общедоступное значение, внутри метода допустимо вначале объявлять, а затем инициализировать литералом. Чтобы применить статическое объявление к сложному
Когда выполняется присваивание совместимых объектов
В значимых типах конструктор по умолчанию зарезервирован и его перегружать нельзя, даже если определены пользовательские конструкторы. В ссылочном типе - классе конструктор без параметров нужно обязательно перегрузить, если его предполагается использовать вместе с добавленными параметризованными конструкторами.
using System;
namespace Test
{
class Program
{
static void Main()
{
new Some();
Console.ReadLine();
}
}
struct Point
{
int x, y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public void Show()
{
Console.WriteLine("x={0}; y={1}", x, y);
}
}
class Some
{
//Point point;
public Some()
{
Point point = new Point();
point.Show();
}
}
}
Иногда может потребоваться хранить object, поскольку класс object является порождающим для всех типов C#. Такой процесс называется упаковкой значимого объекта. Синтаксис упаковки такой
object refValue = point;
Среда выполнения сама зарезервирует место в динамической области памяти и скопирует туда все данные
Упакованный объект можно передать как ссылочный параметр любому внешнему методу. Обратный процесс получения значимого объекта по его ссылке называется распаковкой. По ссылке упакованного объекта нельзя обратиться к его членам. Для этого объект нужно распаковать. Синтаксис распаковки такой
Point point = (Point)refValue;
Ссылка на упакованный объект приводится с помощью явного преобразования к самому объекту того же типа. Типы упакованного и распакованного объектов должны быть совместимы, т.е. иметь одинаковую структуру данных и функций (из чего упаковали, в то и распаковываем).
Экземпляр класса (объект), размещенный при выполнении метода в управляемой куче и адресуемый в программе по ссылке, называется упакованным. Структура или перечисление, размещаемые при выполнении метода в стеке потока, называются распакованными. Здесь речь идет только о членах-данных этих программных единиц.
Поскольку структуры производятся от класса Systcode.ValueType, который, в свою очередь произошел от класса Systcode.Object, то Systcode.Object. Такая процедура называется упаковкой.
И наоборот, если есть ссылка на упакованный
using System;
namespace Test
{
struct Point
{
// Поля
public int x, y;
// Конструктор
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Функция доступа
public void Set(int x, int y)
{
this.x = x;
this.y = y;
}
// Печать
public void Show(string message)
{
Console.WriteLine(message + "x={0}, y={1}", x, y);
}
}
// Класс с функцией Main не может иметь экземпляр
// Поэтому все функции в этом классе должны быть статическими
class EntryPoint
{
static Point valPoint3; // Поле в объекте-типе
static void Main(string[] args)
{
// Настройка консоли
Console.Title = "";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Point valPoint = new Point(5, 10);// Инициализировали и поместили в стек
valPoint.Show("Исходный объект в стеке: ");
object refPoint = valPoint;// Упаковка: ссылка в стеке, объект в куче
((Point)refPoint).Show("\nИсходный объект в куче: ");
object refPoint1 = refPoint;// Еще одна ссылка на объект в куче
CreatePackPoint(ref refPoint1);// Создали еще один объект в куче
((Point)refPoint1).Show("\nНовый объект в куче: ");
Point valPoint1 = new Point();
valPoint1.Show("\nЕще один локальный объект в стеке: ");
Point valPoint2;// Статическое объявление локального объекта
valPoint2.x = 50;// Обязательная инициализация
valPoint2.y = 70;// Обязательная инициализация
valPoint2.Show("\nИ еще один локальный объект в стеке: ");
valPoint3.Show("\nОбъект-поле в типе: ");
Console.ReadLine();// Для задержки окна
}
static void CreatePackPoint(ref object arg)
{
Point point = (Point)arg;// Распаковываем
point.Set(20, 30);// Изменяем
arg = point;//Опять упаковываем
}
}
}
Процесс упаковки выполняется автоматически при передачи объекта методу в случае, если метод ожидает упакованный объект, а ему в качестве аргумента передается распакованный объект.
using System;
namespace Test
{
// Значимый тип, данные размещаются в стеке
struct Point
{
// Закрытые поля
int x, y;
// Конструктор
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Функция доступа
public void Set(int x, int y)
{
this.x = x;
this.y = y;
}
// Печать
public void Show(string message)
{
Console.WriteLine(message + "x={0}, y={1}", x, y);
}
}
// Класс с функцией Main может иметь экземпляр
// Необязательно все функции в этом классе должны быть статическими
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Автоматическая упаковка аргумента метода";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Point valPoint = new Point(5, 10);// Инициализировали и поместили в стек
valPoint.Show("Распакованный объект вне метода: ");
Program prg = new Program();//!!!!!
prg.AutoPackPoint(valPoint);// Создали еще один объект в куче
valPoint.Show("Распакованный объект вне метода: ");
Console.ReadLine();// Для задержки окна
}
// Метод ожидает упакованный объект, поэтому
// автоматически упаковывает распакованный аргумент
void AutoPackPoint(object arg)
{
// Проверим тип для подстраховки, чтобы не вызвать исключение
if (arg is Point)
{
Point point = (Point)arg;// Распаковываем
point.Set(20, 30);// Изменяем
point.Show("Распакованный объект внутри метода: "); // Печатаем
}
else
Console.WriteLine("Вы прислали не Point!");
}
}
}

Если метод ожидает сам значимый объект, то ссылку на объект передавать нельзя и ее нужно вручную распаковать.
using System;
namespace Test
{
// Класс с функцией Main не может иметь экземпляр
// Поэтому все функции в этом классе должны быть статическими
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Распаковка аргумента метода вручную";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Point valPoint = new Point(5, 10);// Инициализировали и поместили в стек
valPoint.Show("Распакованный объект вне метода: ");
object refPoint = valPoint;// Упаковали значимый объект
ManualUnPackPoint((Point)refPoint);// Распаковываем вручную
Console.ReadLine();// Для задержки окна
}
// Метод ожидает распакованный объект, распаковка
// должна выполняться вручную для контроля типов
static void ManualUnPackPoint(Point arg)
{
arg.Set(20, 30);// Изменяем распакованную копию
arg.Show("Копия объекта внутри метода: "); // Печатаем
}
}
}
namespace Test
{
// Значимый тип, данные размещаются в стеке
struct Point
{
// Закрытые поля
int x, y;
// Конструктор
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
// Функция доступа
public void Set(int x, int y)
{
this.x = x;
this.y = y;
}
// Печать
public void Show(string message)
{
Console.WriteLine(message + "x={0}, y={1}", x, y);
}
}
}

Перечисления ( enumerations ) относятся к Int32.
модификатор_доступа enum имя_типа{список_членов}
Список членов представляет собой список идентификаторов, разделенных запятыми. internal - в пределах сборки. Для использования во внешней сборке нужно объявлять public (как и классы).
using System;
namespace Test
{
// Значимый тип, данные размещаются в стеке
enum Fruit // Фрукты
{
Apples, // Яблоки
Plums, // Сливы
Cherries, // Вишни
Grapes, // Виноград
Pears // Груши
}
// Класс с функцией Main не может иметь экземпляр
// Поэтому все функции в этом классе должны быть статическими
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Использование перечислений";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
string[] colorFruit = { // Массив цветов
"Красный",
"Синий",
"Вишневый",
"Зеленый",
"Черный"
};
string[] nameFruit = { // Массив имен
"Яблоки",
"Сливы",
"Вишни",
"Виноград",
"Груши"
};
// Объявляем переменную перечислимого типа
Fruit fruit;
// Используем переменную перечисления для обхода всех членов
for (fruit = Fruit.Apples; fruit <= Fruit.Pears; fruit++)
Console.WriteLine(fruit + " имеет
значение " + (int)fruit);
// Используем переменную перечисления для индексации массива
Console.WriteLine();// Прогон строки
for (fruit = Fruit.Apples; fruit <= Fruit.Pears; fruit++)
Console.WriteLine("Цвет фрукта " + fruit
+ " (" + nameFruit[(int)fruit] +
") - " + colorFruit[(int)fruit]);
Console.ReadLine();// Для задержки окна
}
}
}

Значения списка перечислений по умолчанию начинаются с нуля. Но любому члену списка можно явно присвоить значение, тогда для всех последующих членов списка начнется новая точка отсчета значений натурального ряда чисел.
enum Fruit // Фрукты
{
Apples, // = 0
Plums, // = 1
Cherries = 100,
Grapes, // = 101
Pears // = 102
}
Элементы перечисления можно инициализировать в любой последовательности, закрепляя за
enum Fruit // Фрукты
{
Apples = 21,
Plums = 101,
Cherries = 100,
Grapes = 12,
//Grapes = 3,
Pears = 12
}
Элементы перечисления, как Int3 2 и занимает 4 байта. Ситуацию можно изменить, задав другой byte ) для всех элементов перечисления по следующему синтаксису
enum Fruit : byte // Фрукты
{
Apples = 21,
Plums = 101,
Cherries = 100,
Grapes = 12,
Pears = 2
}
using System;
namespace Test
{
enum Fruit // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
enum Fruit1 : byte // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
enum Fruit2 : long // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
class EntryPoint
{
static void Main()
{
// Настройка консоли
Console.Title = "Использование перечислений";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
Console.WriteLine("Члены Fruit имеют размер по "
+ sizeof(Fruit) + " байта");
Console.WriteLine("Члены Fruit1 имеют размер по "
+ sizeof(Fruit1) + " байту");
Console.WriteLine("Члены Fruit2 имеют размер по "
+ sizeof(Fruit2) + " байт");
Console.ReadLine();// Для задержки окна
}
}
}

Перечисления могут быть и членами класса
using System;
namespace Test
{
class EntryPoint
{
enum Fruit // Фрукты
{
Apples,
Plums,
Cherries,
Grapes,
Pears
}
static void Main()
{
// Настройка консоли
Console.Title = "Использование перечислений";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Объявляем переменную перечислимого типа
Fruit fruit;
// Используем переменную перечисления для обхода всех членов
for (fruit = Fruit.Apples; fruit <= Fruit.Pears; fruit++)
Console.WriteLine(fruit + " имеет
значение " + (int)fruit);
Console.ReadLine();// Для задержки окна
}
}
}

Приведенные способы применения перечислений встречаются очень редко, чаще используется прямое назначение перечислений как набора именованных целочисленных констант, упакованных в одном блоке кода. Библиотека .NET Framework содержит множество полезных перечислений, облегчающих программисту жизнь. Одно из таких перечислений System.Windows.Forms.Keys, содержащееся в одноименной библиотечной сборке System.Windows.Forms.dll.
using System;
using System.Windows.Forms;
using System.Drawing;
// Подключить через оболочку соответствующие сборки!!!!!!!!!!!
namespace Test
{
class MyClass : Form
{
// Сообщение в окне
string messageKey = "Нажимайте клавиши";
public MyClass() // Конструктор формы
{
// Настройка формы
try // Безопасный код загрузки иконки
{
this.Icon = new Icon("1.ICO");
}
catch { /* На исключения не реагировать */ }
this.Text = "Перечисление Keys";
this.Font = new Font("Arial", 14, FontStyle.Bold);
}
// Перегрузка метода OnPaint(), наследуемого от класса Control
protected override void OnPaint(PaintEventArgs e)
{
Form frm = this;
Graphics gr = e.Graphics;// Контекст экрана
// Создаем и настраиваем точку привязки текстового блока
StringFormat strfrm = new StringFormat();
strfrm.Alignment = StringAlignment.Center;// Центр по горизонтали
strfrm.LineAlignment = StringAlignment.Center;// Центр по вертикали
// Точка привязки на форме
PointF point = new PointF(frm.ClientSize.Width / 2,
frm.ClientSize.Height / 2);
// Выводим содержимое строки поля класса
gr.DrawString(messageKey,
frm.Font, // Применяется шрифт окна
new SolidBrush(Color.Red), // Цвет шрифта
point, // Точка привязки на форме
strfrm); // Передаем точку привязки текстового блока
// Выполняем обработчик события до полной глубины наследования
base.OnPaint(e);
}
// Перегрузка метода OnKeyUp(), наследуемого от класса Control
protected override void OnKeyUp(KeyEventArgs e)
{
// Временно сохраняем подсказку
string mess = messageKey;
// Анализируем нажатую клавишу
switch (e.KeyCode)
{
case Keys.X:
case Keys.Enter:
case Keys.Escape:
messageKey = "Нажата клавиша " + e.KeyCode
+ "\nAscii-код клавиши " + (byte)(e.KeyCode)
+ "\nЧто-то делаем...";
break;
case Keys.Space:
messageKey = "Нажата клавиша " + Keys.Space
+ "\nAscii-код клавиши " + (byte)(Keys.Space)
+ "\nЧто-то делаем...";
break;
default:
messageKey = "Нажата " + e.KeyCode
+ "\nAscii-код клавиши " + (byte)(e.KeyCode)
+ "\nОна нам не нужна!";
break;
}
// Инициируем немедленную перерисовку формы
// для вывода нового сообщения
this.Refresh();
//this.Invalidate(); // Удаляется из очереди при задержке потока
// Усыпляем текущий поток на две секунды
System.Threading.Thread.Sleep(2000);
// Восстанавливаем подсказку
messageKey = mess;
// Инициируем перерисовку формы
// для вывода восстановленной подсказки
this.Invalidate();
// Выполняем обработчик события до полной глубины наследования
base.OnKeyUp(e);
}
}
}
namespace Test
{
class EntryPoint
{
static void Main()
{
// Настройка стиля формы
Application.EnableVisualStyles();
// Цикл сообщений Windows
Application.Run(new MyClass());
}
}
}

Как только в приложении объявляется перечисление, тем самым неявно объявляется тип, производный от абстрактного класса System.Enum. Например, даже вот такой пустой код
internal enum MyEnum
{
}
internal class EntryPoint
{
static void Main()
{
}
}
дает следующую диаграмму в панели Class View оболочки

Базовый класс System.Enum является абстрактным, поэтому не может напрямую иметь экземпляры (объекты), а может использоваться только как базовый в цепочке наследования. Тем не менее он определяет ряд статических методов, позволяющих обрабатывать созданные перечисления. Вот некоторые из этих методов.
| Метод | Описание |
|---|---|
public static string Format(System.Type enumType, object value, string format) |
Преобразует значение данного типа перечисления в эквивалентное строковое представление в соответствии с указанным форматом |
public static string GetName(System.Type enumType, object value) |
Возвращает имя для константы с указанным значением |
public static string[] GetNames(System.Type enumType) |
Возвращает массив имен для константы с указанным значением |
public static System.Type GetUnderlyingType(System.Type enumType) |
Возвращает численный тип данных, используемый для хранения значений данного перечисления |
public static System.Array GetValues(System.Type enumType) |
Возвращает массив элементов указанного перечисления |
public static bool IsDefined(System.Type enumType, object value) |
Возвращает флаг существования в указанном перечислении заданного элемента |
public |
Упаковывает в объектную ссылку один или несколько элементов перечисления по их именам, заданным в строке |
public |
Упаковывает в объектную ссылку один или несколько элементов перечисления по их именам, заданным в строке |
Приведем пример программы, использующей статические методы класса System.Enum.
using System;
namespace CHETKOB.Test
{
internal enum Fruit // Фрукты
{
Apples = 102, // Яблоки
Plums = 12, // Сливы
Cherries = 50, // Вишни
Grapes = 11, // Виноград
Pears = 211 // Груши
}
internal class MyClass
{
static void Main()
{
// Настройка консоли
Console.Title = "Методы библиотечного класса Enum";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Анализируем перечисление Fruit
Array fruitArray = Enum.GetValues(typeof(Fruit));
Console.WriteLine("Определяем количество
членов перечисления:");
Console.WriteLine("Перечисление содержит {0}
членов", fruitArray.Length);
// Обходим все члены перечисления
// и выводим пары "ключ-значение"
Console.WriteLine("\nВыводим элементы перечисления:");
foreach (Fruit fruit in fruitArray)
{
Console.Write("{0, -8} = {1, -3} ",// Количество знакомест
fruit.ToString(),
Enum.Format(typeof(Fruit), fruit, "D")); // Decimal - десятичный
Console.WriteLine("(= 0x{0})",
Enum.Format(typeof(Fruit), fruit, "X"));// Hex - шестнадцатиричный
}
// Ищем элемент по значению
Console.WriteLine();
Console.WriteLine("Ищем элемент по значению:");
foreach (Fruit fruit in fruitArray)
{
int value = (int)fruit;
Console.WriteLine("Значение {0, -3}
имеет элемент {1}", value,
Enum.GetName(typeof(Fruit), value));
}
// Проверяем, есть ли элемент в указанном перечислении
Console.WriteLine();
Console.WriteLine("Проверяем существование
элемента в перечислении:");
string element = "Apples";
if (Enum.IsDefined(typeof(Fruit), element))
Console.WriteLine("Элемент {0} в
перечислении есть", element);
else
Console.WriteLine("Элемента {0} в
перечислении нет", element);
// Печатаем еще одно перечисление
Console.WriteLine();
Console.WriteLine("Печатаем еще одно перечисление:");
Type weekdays = typeof(Days);
foreach (string str in Enum.GetNames(weekdays))
Console.WriteLine("{0,-11} = {1}",
str,// Резервирует 11 знакомест
Enum.Format(weekdays, Enum.Parse(weekdays, str), "d"));
Console.ReadLine();
}
// Перечисление в классе. Доступ из других класов
// сборки будет составным: MyClass.Days
internal enum Days
{
Понедельник, Вторник, Среда, Четверг,
Пятница, Суббота, Воскресенье
};
}
}

| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
sbyte |
- | SByte |
-128 - 127 | Знаковое 8 бит |
byte |
+ | Byte |
0 - 255 | Беззнаковое 8 бит |
short |
+ | Int16 |
-32'768 - 32'767 | Знаковое 16 бит |
ushort |
- | UInt16 |
0 - 65'535 | Беззнаковое 16 бит |
int |
+ | Int32 |
-2'147'483'648 - 2'147'483'647 | Знаковое 32 бит |
uint |
- | UInt32 |
0 - 4'294'967'295 | Беззнаковое 32 бит |
long |
+ | Int64 |
-9'223'372'036'854'775'808 - 9'223'372'036'854'775'807 | Знаковое 64 бит |
ulong |
- | UInt64 |
0 - 18'446'774'073'709'551'615 | Беззнаковое 64 бит |
Префикс s означает " signed " - знаковый; u - " unsigned " - беззнаковый
Наибольшее распространение имеет тип int, поскольку его диапазона значений вполне хватает для вспомогательных операций.
using System;
namespace Test
{
class Inches
{
static void Main()
{
long inches;
long miles = 93000000; // Миль до Солнца
// 5280 футов в миле, 12 дюймов в футе
inches = miles * 5280 * 12;
Console.WriteLine("Расстояние до Солнца: "
+ inches
+ " дюймов.");
Console.Read();
}
}
}
Тип byte предназначен для хранения чисел без знака от 0 до 255 размером 8 битов и полезен при обработке двоичных данных.
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
sbyte |
- | SByte |
-128 - 127 | Знаковое 8 бит |
byte |
+ | Byte |
0 - 255 | Беззнаковое 8 бит |
using System;
namespace Test
{
class UseByte
{
static void Main()
{
byte x;
int sum = 0;
for(x = 1; x <= 100; x++)
sum += x;
Console.WriteLine("Сумма чисел от
1 до 100 равна " + sum);
Console.Read();
}
}
}
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
float |
+ | Single |
1.5x10-45 - 3.4x1038 | Знаковое с плавающей точкой 32 бит |
double |
+ | Double |
5.0x10-324 - 1.7x10308 | Знаковое с плавающей точкой 64 бит |
Чаще всего используется тип double, поскольку он поддерживается множеством математических функций библиотеки .NET Framework. Большинство математических функций сосредоточено в классе System.Math
using System;
namespace Test
{
// Нахождение радиуса круга по его площади
class FindRadius
{
static void Main()
{
double radius, area = 10.0;
radius = Math.Sqrt(area / Math.PI);
Console.WriteLine("Площадь круга:
{0};", area);
Console.WriteLine("Радиус круга:
{0};", radius);
Console.Read();
}
}
}
using System;
namespace Test
{
// Использование тригонометрических методов
class Trigonometry
{
static void Main()
{
for(int i = 0; i < 3; i++) // Внешний цикл
{
// alpha - угол в градусах
for(double alpha = 0D; alpha <= 180; alpha = alpha + 10)
{
switch(i + 1)
{
case 1: Console.WriteLine("Sin({0})={1}",
alpha, Math.Sin(alpha / 180 * Math.PI));
break;
case 2: Console.WriteLine("Cos({0})={1}",
alpha, Math.Cos(alpha / 180 * Math.PI));
break;
case 3: Console.WriteLine("Tan({0})={1}",
alpha, Math.Tan(alpha / 180 * Math.PI));
break;
}
}
Console.WriteLine();
}
Console.Read();
}
}
}
Предназначен для выполнения вычислений, связанных с денежными единицами.
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
decimal |
+ | Decimal |
10-28 —1028 | Знаковое 128 бит |
Применение обычной арифметики с плавающей точкой чревато ошибками округления. Во избежании этих ошибок и предназначен тип decimal.
using System;
namespace Test
{
// Использование типа decimal для вычисления скидки
class UseDecimal
{
static void Main()
{
decimal price; // Цена
decimal discount; // Скидка
decimal discounted_price; // Цена со скидкой
// Вычисляем цену со скидкой
price = 19.95M; // Цена товара
discount = 0.15m; // Ставка дисконта равна 15%
discounted_price = price - (price * discount);// Скобки не обязательны
Console.WriteLine("Цена со скидкой: $"
+ discounted_price);
Console.Read();
}
}
}
using System;
namespace Test
{
/*
* Использование типа decimal для вычисления
* будущей стоимости капиталовложений
*/
class UseDecimal
{
static void Main()
{
decimal amount; // Исходный вклад
decimal rate_of_return; // Норма прибыли
int years; // Количество лет
amount = 1000M;
rate_of_return = .07m;
years = 10;
Console.WriteLine("Исходный вклад:
$" + amount);
Console.WriteLine("Норма прибыли:
" + rate_of_return);
Console.Write("Через " + years +
" лет будет $");
for(int i = 0; i < years; i++)
amount += amount * rate_of_return;
Console.WriteLine(amount);
Console.Read();
}
}
}
В C# исмволы представлются не в однобайтном коде ASCII, а в двухбайтном коде Unicode. Это позволяет представлять алфавиты всех существующих в мире языков. Это 16 - разрядный тип без знака.
| Псевдоним C# | Соответствие CLS | Системный тип | Диапазон | Пояснения |
|---|---|---|---|---|
char |
+ | Char |
U+0000 - U+FFFF | Для описания только одного символа Unicode 16 бит |
Символьной переменной можно присвоить значение, заключив соответствующий символ в одинарные кавычки. Например
char ch; ch = 'X';
using System;
namespace Test
{
class UseDecimal
{
static void Main()
{
char ch0 = 'П', ch1 = 'р',
ch2 = 'и', ch3 = 'в',
ch4 = 'е', ch5 = 'т';
Console.WriteLine((int)ch0);
Console.WriteLine((int)ch1);
Console.WriteLine((int)ch2);
Console.WriteLine((int)ch3);
Console.WriteLine((int)ch4);
Console.WriteLine((int)ch5 + "\n");
Console.WriteLine(ch0 + ch1 + ch2 + ch3 + ch4 + ch5);
Console.WriteLine();
Console.WriteLine(ch0);
Console.WriteLine(ch1);
Console.WriteLine(ch2);
Console.WriteLine(ch3);
Console.WriteLine(ch4);
Console.WriteLine(ch5 + "\n");
Console.WriteLine("{0}{1}{2}{3}{4}{5}\n",
ch0, ch1, ch2, ch3, ch4, ch5);
string str = Convert.ToString(ch0)
+ Convert.ToString(ch1)
+ Convert.ToString(ch2)
+ Convert.ToString(ch3)
+ Convert.ToString(ch4)
+ Convert.ToString(ch5);
Console.WriteLine(str);
Console.Read();
}
}
}
Тип bool в C# представляет логические значения true или false ( ИСТИНА/ЛОЖЬ ), которые можно использовать в операторах управления (условия, циклы).
using System;
namespace Test
{
class UseBool
{
static void Main()
{
bool logical;
logical = false;
int i;
for(i = 0; i < 2; i++)
{
logical = !logical;
Console.Write("logical={0}: ", logical);
if(logical)
Console.WriteLine("Привет от Иванова!");
else
Console.WriteLine("Привет от Петрова!");
}
Console.WriteLine("10 > 9 равно " + (10 > 9));
Console.Read();
}
}
}
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.