Информационные технологии. Язык программирования C#.
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Информационные технологии. Язык программирования C#.

Лекции, прочитанные А.Г.Мацкевичем на потоке БРТ в 2013-14 и 2014-15 гг.

Лекция 1

Введение

Основы C#

Оператор присваивания.

Арифметические, логические операторы, операторы отношения.

Приоритеты выполнения операторов в выражении.

Преобразование данных

Способы вывод и ввода данных в консольном режиме

Последовательная программа

Лекция 2

Методы

Лекция 3

Разветвления

Условный оператор

Оператор выбора switch

Сокращенная проверка

Лекция 4

Введение в ООП. Объекты, классы.

Инкапсуляция, наследование, полиморфизм.

Модификаторы доступа public и private.

Лекция 5

Оконный режим

Программирование с управлением по событиям и ООП

Визуальное программирование и ООП  

Пример решения задачи про углы в оконном режиме

Лекция 6

Где же метод Main() в оконных приложениях. Режим DEBUG.

Обещанное в предыдущих лекциях: перегрузка методов, конструкторы в классах, закрытые поля, свойства.

Модификатор static.

Перегрузка методов. Конструкторы.

Текущий объект, this.

Закрытые поля, свойства.

Лекция 7

Циклы.

Операторы while, do … while, for.

(foreach в лекции 8)

Конец первого семестра

Второй семестр

Лекция 8

Массивы.

Цикл Foreach.

Наследование. Модификатор доступа protected.

Лекция 9

Двумерные массивы.

Класс Array.

Класс ArrayList.

Лекция 10

Строки

Символы char

Неизменяемые строкиstring

Операции над строками

Методы класса string

Изменяемые строки StringBuilder

Лекция 11

Потоки.

Текстовые файлы.

Бинарные файлы.

Лекция 12

Продвинутое программирование:

Структуры

Индексаторы

Тип var

Шаблоны.

Лекция 13

Платформа .NET. Теперь об этом можно поговорить!

Приложение 1.(Первое лабораторное занятие второго семестра)

Повторное использование кода. Создание и использование DLL.

 

 

Материалы второго семестра

Лекция 8

Массивы.

Цикл Foreach.

Лекция 9

Двумерные массивы.

Класс Array.

Класс ArrayList .

Двумерные массивы – это частный случай многомерных массивов, которые, формально, имеют более одного измерения. В программах двумерные массивы используются чаще, чем другие многомерные массивы. Может быть, это происходит потому, что двумерные массивы, по сути, являются аналогами матриц из классической математики, а вот массивы с большим числом измерений в математике, конечно, используются, но не повсеместно.

Варианты описания двумерного массива:

 

тип[,] имя;

тип[,] имя = new тип [ разм_1, разм_2 ];

тип[,] имя = { список_инициализаторов };

тип[,] имя = new тип [,] { список_инициализаторов };

тип[,] имя = new тип [ разм_1, разм_2 ] { список_инициализаторов };

 

Примеры описаний (один пример на каждый вариант описания):

 

int[,] a;                   // элементов нет

int[,] b = newint[2, 3]; // элементы равны 0

int[,] c = {{1, 2, 3}, {4, 5, 6}}; // new подразумевается

int[,] c = newint[,] {{1, 2, 3}, {4, 5, 6}};//размерность вычисляется

int[,] d = newint[2,3] {{1, 2, 3}, {4, 5, 6}};// 5 избыточное описание

 

К элементу двумерного массива обращаются, указывая номера строки и столбца, на пересечении которых он расположен, например:

 

a[1, 4]   b[i, j]   b[j, i]

Ну а теперь нужен пример работы с двумерными массивами.

Задача: в прямоугольной матрице ищется номера максимальных элементов в строках, создается одномерные массив из этих данных и элементы с этими номерами выставляются на место последнего элемента строки исходной матрицы (в последний столбец).

Для решения этой задачи создана иерархия двух классах: в классе-предке class CMatrорганизованы закрытые поля и соответствующие открытые свойства для хранения размерностей матрицы, самой матрицы и вектора из номеров максимальных элементов в строках матрицы. Обратите внимание, как описываются свойства, связанные с закрытыми полями-массивами. Кроме этого написаны два метода: метод publicvoid FindIndMax()для иницилизации и заполнения значениями одномерногомассива из номеров максимальных элементов строк матрицы и метод

publicdouble [,] ChangeMatr()

для перестановки максимальных элементов в последний столбец матрицы. Обратите внимание, что на тип возвращаемого результата этих методов.

В классе-наследнике class MatrIO : CMatrнаписаны методы формирования исходной матрицы с именами InputMatr, метод вывода OutPutMatr(ListBox lb)матрицы в оконный элемент класса ListBoxи метод вывода одномерного массива OutPutVekt(ListBox lb)в ListBox.

Файл Class1.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Forms;

//using System.Collections;//

 

namespace WinApMatr

{

classCMatr

{

privateintm;//закрытоеполе - количествостроквматрице

publicint M //свойство

   {

get {return m;} set { m = value; }

}

privateint n;//закрытое поле - количество столбцов в матрице

publicint N//свойство

   {

get { return n; }

set { n = value; }

   }

privatedouble[,] matr;//закрытоеполе - двумерныймассив (матрица)

publicdouble[,] Matr//свойство

   {

get { return matr; }

set { matr = value; }

   }

privateint[] maxind;//закрытоеполе - одномерныймассив (вектор)

publicint[] Maxind//свойство

   {

get { return maxind; }

set { maxind = value; }

   }

 

/**/

publicvoid FindIndMax()

// формирует массив из индексов макс.элементов строк матрицы

// метод работает непосредственно с полями класса: c двумерным массивом matr и одномерным массивом maxind

{

       Maxind=newint[M];

for (int i=0; i<M;i++)

       {

double max = Matr[i, 0]; int jmax = 0;

for (int j = 0; j < N; j++)

           {

if (max < Matr[i,j])

               { max = Matr[i, j]; jmax = j; }

           }

           Maxind[i] = jmax;

       }

   }

 

publicdouble[,] ChangeMatr()

//Из матрицы matr формирует локальную матрицу с именем a,

//в которой меняются местами элемент с макс.значением и последний элемент

//метод возвращает не одно значение, а весь массив (матрицу a)

{

double[,] a = newdouble[M, N];

       a = Matr;

double z;

for (int i = 0; i < M; i++)

       {

           z = a[i, N-1];

           a[i, N-1] = a[i, Maxind[i]];

           a[i, Maxind[i]] = z;

}

return a;

   }

/**/

}

 

classMatrIO : CMatr//К методам класса CMatr добавлены методы формирования и вывода матрицы

{

publicvoid InputMatr(bool k)

   {

       Matr = newdouble[,] {{11,2,3},

                             {4,5,6}};

       M = Matr.GetLength(0);

       N = Matr.GetLength(1);

   }

 

publicvoid InputMatr()

//формирует матрицу matr специальным образом

   {

Matr = newdouble[M, N];

for (int i = 0; i < M; i++)

       {

for (int j = 0; j < N; j++)

           {

               Matr[i, j] = i - j;

if (i==j) Matr[i,j]=10+i;

}

       }

   }

 

publicvoid InputMatr(int k) // перегрузкаметода InputMatr

//Формирует матрицу из случайных целых чисел в интервале (-5,5)

{

       Matr = newdouble[M, N];

Random rnd = newRandom();

for (int i = 0; i < M; i++)

       {

for (int j = 0; j < N; j++)

{

               Matr[i, j] = rnd.Next(0,10) - 5;

           }

       }

   }

publicvoid InputMatr(double k) // перегрузкаметода InputMatr

//Формирует матрицу из случайных действительных чисел в интервале (-30,50)

{

       Matr = newdouble[M, N];

Random rnd = newRandom();

for (int i = 0; i < M; i++)

{

for (int j = 0; j < N; j++)

           {

               Matr[i, j] = rnd.NextDouble()*80-30;

}

       }

   }

publicvoid OutPutMatr(ListBox lb)

{

// MessageBox.Show("Общееколичествоэлементов L="+Matr.Length.ToString());

// MessageBox.Show("Количество элементов по 0-вой размерности L0=" + Matr.GetLength(0).ToString());

// MessageBox.Show("Количество элементов по 1-вой размерности L1=" + Matr.GetLength(1).ToString());

// Вообще-то,можно обойтись без полей, отвечающих за размерность матрицы, а каждый раз их измерять

lb.Items.Clear();

int M = Matr.GetLength(0);//локальноеимя

int N = Matr.GetLength(1);//локальноеимя

for (int i = 0; i < M; i++)

       {

string s = "";

for (int j = 0; j < N; j++)

           {

               s = s + Matr[i, j].ToString("F2")+" ";// форматныйвывод

           }

           lb.Items.Add(s);

       }

   }

 

publicvoid OutPutVekt(ListBox lb)

   {

       lb.Items.Clear();

for (int i = 0; i < M; i++)

       {

          lb.Items.Add(Convert.ToString(Maxind[i]));

}

 

   }

}

}

 

 

Файл Form1.cs

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WinApMatr

{

publicpartialclassForm1 : Form

{

public Form1()

   {

       InitializeComponent();

   }

 

MatrIO mm;//объявлениепеременой mm - объекткласса MatrIO

 

privatevoid Form1_Load(object sender, EventArgs e)

// событие, возникающее при загрузке формы Form1

   {

       mm = newMatrIO();// инициализация объекта mm класса MatrIO

}

 

privatevoid button1_Click(object sender, EventArgs e)

{ // работа с загруженым объектом mm

       mm.M = int.Parse(textBox1.Text);

mm.N = int.Parse(textBox2.Text);

       mm.InputMatr();

       mm.OutPutMatr(listBox1);

   }

 

privatevoid button2_Click(object sender, EventArgs e)

{// работа с загруженым объектом mm

       mm.M = int.Parse(textBox1.Text);

mm.N = int.Parse(textBox2.Text);

       mm.InputMatr(1.5);

       mm.OutPutMatr(listBox1);

   }

 

privatevoid button3_Click(object sender, EventArgs e)

{// работа с загруженым объектом mm

       mm.M = int.Parse(textBox1.Text);

mm.N = int.Parse(textBox2.Text);

       mm.InputMatr(1);

       mm.OutPutMatr(listBox1);

   }

 

privatevoid button4_Click(object sender, EventArgs e)

{// работа с загруженым объектом mm

       mm.FindIndMax();

mm.OutPutVekt(listBox2);

   }

 

privatevoid button5_Click(object sender, EventArgs e)

{// работа с загруженым объектом mm

       mm.Matr = mm.ChangeMatr();

mm.OutPutMatr(listBox3);

   }

 

privatevoid button6_Click(object sender, EventArgs e)

   {//выходизприложения

       Close();

   }

 

privatevoid button7_Click(object sender, EventArgs e)

   {

       mm.InputMatr(true);

       mm.OutPutMatr(listBox1);

}

}

}

Пример 9.1.

 

На рис.9.1 приведен скриншот работы приложения решения этой задачи.

 

Рис.9.2

В этом приложении нет «защиты от дурака» в виде последовательного открытия кнопочек, которые надо давить на следующем шаге решения задачи.

 

Класс Array.

В лекции 8 уже упоминалось, что все массивы есть объекты класса Array. Кроме поля length в этом классе есть и другие поля и методы. Их использованиеупрощает манипулирование массивом как объектом.:

Свойства

Свойство Описание
public intLength {get} Возвращает количество всех элементов массива
public intRank{get} Возвращает количество измерений массива

 

Методы

Метод Описание
public intGetLength(Dimention) Возвращает количество элементов массива по измерению Dimention
public object GetValue(Index) Возвращает значение элемента с индексом Index одномерного массива. Аналогичные есть для многомерных массивов
public static void Reverse(Array) Изменяет порядок следования элементов одномерного массива Array на обратный
public static void CopyTo(Array,Index) Копирует из текущего одномерного массива все элементы в массив Array, начиная с индекса Index
public static void Sort(Array) Сортирует элементы одномерного массива Array
public static void IndexOf(Array)  
public static void BinarySearch(Array)  

Методы с модификатором staticявляются статическими, поэтому к ним обращаются через имя класса, а не используя имя объекта (экземпляра класса), поэтому имя массива передают в них как параметр. Двоичный поиск можно применять только для упорядоченных массивов.

В примере 9.2 представлен исходный текст приложения, в котором использованы методы класса Array.

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1

{

publicpartialclassForm1 : Form

{

public Form1()

   {

       InitializeComponent();

   }

 

MyMassiv ms = null;

 

privatevoid button1_Click(object sender, EventArgs e)

   {

int n = Convert.ToInt32(textBox1.Text);

ms = newMyMassiv();

      ms.InPutMass(n);

      button5.Visible = true;

      button2.Visible = true;

   }

 

privatevoid button2_Click(object sender, EventArgs e)

   {

           ms.Mm = newint[ms.Leng];

           ms.RewZad10();

           button3.Visible = true;

           button4.Visible = true;

   }

 

privatevoid button3_Click(object sender, EventArgs e)

   {

       ms.OutPut(ms.Mm, listBox2);

   }

 

privatevoid button4_Click(object sender, EventArgs e)

   {

       ms.Max = ms.MaxMas();

       button4.Text = "MAX="+Convert.ToString(ms.Max);

   }

 

privatevoid button5_Click(object sender, EventArgs e)

   {

       ms.OutPut(ms.Mass, listBox1);

   }

 

privatevoid button6_Click(object sender, EventArgs e)

   {

         ms = newMyMassiv();

       ms.InPutMass();

 

   }

 

privatevoid button7_Click(object sender, EventArgs e)

   {

int z = Array.IndexOf(ms.Mass, 2);

       button7.Text = " index 2="+Convert.ToString(z);

int[] Ar;

       Ar = newint[ms.Mass.Length];

Array.Copy(ms.Mass, Ar, 3);

// ms.CopyMass(out Ar, 3);

       ms.OutPut(Ar, listBox3);

Array.Sort(ms.Mass);

       ms.OutPut(ms.Mass, listBox4);

       ms.Mass.SetValue(111, 2);//ms.Mass[2]=111

       ms.OutPut(ms.Mass, listBox5);

Array.Reverse(ms.Mass);

       ms.OutPut(ms.Mass, listBox6);

   }

}

 

publicclassMassiv

{

privateint leng; //Закрытоеполе-размермассивов mass и mm

publicint Leng //Свойство для изменения закрытого поля

   {

get { return leng; } //Чтение

set { leng = value; } //Возвращаемое значение

   }

 

privateint[] mass; //Закрытое поле массив

publicint[] Mass // Свойство для описания массива !!!

{

get { return mass; }

set { mass = value; }

   }

privateint[] mm;

publicint[] Mm

   {

get { return mm; }

set { mm = value; }

   }

 

publicvoid RewZad10()

   {

   Mm = newint[Leng];

for (int i = 0; i <= Leng-1; i++)

       {

           Mm[i] = Mass[i] + 10;           

       }

   }

 

publicint MaxMas()

   {

int max;

       max = Mm[0];

for (int i = 0; i <= Leng - 1; i++)

       {

if (Mm[i]>max) max=Mm[i];

       }

return max;

   }

privateint max;

publicint Max

   {

get { return max; } //Чтение

set { max = value; } //Возвращаемое значение

   }

 

publicint Search(int k)

{

int i;

       i = Array.IndexOf(Mass, k);

return i;

   }

publicvoid SortMass()

{

Array.Sort(Mass);

   }

 

publicvoid CopyMass(outint[] Ar,int k)

   {

       Ar = newint[Mass.Length];

Array.Copy(Mass,Ar,3);

   }

}

 

publicclassMyMassiv : Massiv

{

publicvoid InPutMass()

   {

       Mass = newint[] { 7, 6, 5, 4, 3, 2, 1 };

   }

publicvoid InPutMass(int length)

   {

     Leng = length;

     Mass = newint[Leng];          

Random rnd = newRandom();

     rnd.NextDouble();

for (int i = 0; i <= Leng - 1; i++)

     {

           Mass[i] = rnd.Next(1,100)-50;

     }

   }

 

publicvoid OutPut(int[] a, ListBox lb)

   {

if (a != null)

       {

           lb.Items.Clear();

for (int i = 0; i <= a.Length - 1; i++)

           {

               lb.Items.Add(a[i]);

}

       }

   }

}

/* */

}

Пример 9.2

 

Результат работы представлен на Рис.9.3.

Рис.9.3

 

Класс ArrayList .

Недостатком массивов класса Array является то, что их размерность (количество элементов) должно быть известно заранее и после инициализации это значение менять нельзя. Этого недостатка лишены массивы из класса ArrayList. Ниже приведены некоторые методы этого класса, среди которых, конечно, надо выделить метод A dd, с помощью которого к массиву можно добавлять еще один элемент. Элементы массива класса ArrayList объявлены классом o bject, то есть, по сути, могут быть элементами любого класса.

К чему это приводит? Продемонстрируем это на простом примере. Есть массив с элементами типа do u ble или любого другого числового типа. Количество элементов заранее неизвестно, поэтому для хранения используем класс ArrayList. Надо вычислять сумму элементов или какую-нибудь другую агрегатную величину, для получения которой необходимо использовать арифметические операции. Напрямую элементы этого массива использовать не удастся. Почему? Это элементы класса object, а их складывать нет возможности. Придется их конвертировать к типу double, или к другому числовому типу, а потом уже складывать.

Есть ли недостатки у класса ArrayList по сравнению с классом Array?Да, конечно. Во-первых, представителями этого класса могут быть только одномерные массивы, во-вторых, программы, использующие этот класс, работают существенно медленнее, чем с массивами класса Array.

Да, чуть не забыл. Для работы с ArrayList надо подключить пространство имен Collections:usingSystem.Collections;

В таблице 9.1 приведены методы ( не все ) класса ArrayList.

Метод класса ArrayList Описание
int Add(Object Value) Добавляет в конец списка новый объект и возвращает его индекс
void Clean() Удаляет все элементы коллекции
bool Contains(Object Value) Возвращает true, если коллекция содержит элемент Value
int Count{get} Свойство, предназначенное только для чтения, хранит текущую длину коллекции.
intIndexOf(Object Value) Возвращает индекс первого вхождения элемента со значением Value
intLastIndexOf(Object Value) Возвращает индекс последнего вхождения элемента со значением Value
void Insert(int Index; Object Value ) Вставляет элемент Value в нужное место Index коллекции
Object this[index] {get;set} Это свойство позволяет обратиться к элементу по индексу
void Remove(Object Value) Удаляет из коллекции первое вхождение элемента со значением Value.
void RemoveAt(int Index) Удаляет элемент по индексу
void RemoveRange(intIndex; int Count) Удаляет из коллекции ровно Count элементов начиная с индекса Index
void Reverse() Изменяет порядок следования элементов на обратный
void Sort() Сортирует коллекцию
intBinarySearch(Object Value) Отыскивает элемент Value в отсортированном списке и возвращает его индекс или отрицательное число, если он не найден

Таблица 9.1

 

А в примере 9.3 продемонстрировано использованиеметодов класса ArrayList для работы с массивом целых чисел.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Collections; //добавили

 

namespace WinFormArrayList

{

publicpartialclassForm1 : Form

{

public Form1()

   {

       InitializeComponent();

   }

 

privatevoid button1_Click(object sender, EventArgs e)

   {

ArListIO ar= newArListIO();

       ar.InputArray();// заполнили ar.A

       ar.OutPutArray(ar.A, listBox1);// вывели

int s=ar.Summa(); // вычислили сумму элементов

label9.Text = "Суммаэлементов=" + Convert.ToString(s);

ar.A.Add(20);// добавили в конец

ar.A.Add(10);

       ar.OutPutArray(ar.A, listBox2);

       ar.A.Sort();// сортировка

       ar.OutPutArray(ar.A, listBox8);

ar.A.Reverse();// изменяет порядок следования элементов на обратный

ar.OutPutArray(ar.A, listBox9);

ar.A.Remove(3);// удаляет элемент со значение 3

ar.OutPutArray(ar.A, listBox3);

ar.A.RemoveAt(4);// удаляет элемент с индексом 4

ar.OutPutArray(ar.A, listBox4);

ar.A.RemoveRange(1, 3);//удаляет элементы начиная с индекса 1 до индекса 3

// удаляет элементs с индекса 1 до индекса 3

ar.OutPutArray(ar.A, listBox7);

ar.A.Insert(1, 3);//вставили по индексу 1 значение 3

       ar.A[ar.A.Count-1]=3;//изменили последний элемент

ar.OutPutArray(ar.A, listBox5);

int first = ar.A.IndexOf(3);// ищет индекс первого вхождения значения 3

int last=ar.A.LastIndexOf(3);// ищет индекс последнего вхождения значения 3

       label4.Text = "индекс первого вхождения значения 3=" + Convert.ToString(first);

       label5.Text = "индекс последнего вхождения значения 3=" + Convert.ToString(last);

       ar.A.Clear();// очистили массив

       ar.OutPutArray(ar.A, listBox6);

}

}

 

publicclassAr

{

// private ArrayList a;

publicArrayList A { get; set; }

publicint Summa()

   {

int s = 0;

foreach (int x in A)

s = s + (int)x; //явное приведение типа

return s;

   }

}

 

publicclassArListIO : Ar

{

publicvoid InputArray()

   {

       A = newArrayList { 7, 6, 5, 4, 3, 2, 1 };

 

   }

publicvoid OutPutArray(ArrayList x,ListBox lb)

   {

int i;

       lb.Items.Clear();

if (x.Count == 0)

           lb.Items.Add("пусто");

else

       {

for (i = 0; i <= x.Count - 1; i++)

           {

               lb.Items.Add(x[i]);

}

       }

   }

}

}

 

Пример 9.3

 

Обратите внимание на метод Summa() класса Ar. В нем вычисляется сумма элементов массива и здесь приходится использовать явное приведение типадля того, чтобы c элементами массива, являющиеся объектами класса object можно было работать как с числами.

Рис.9.4

Лекция 10

Строки

Обработка текстовой информации является одной из самых распространенных задач современного программировании. С# предоставляет для ее решения широкий набор средств: символы char, неизменяемые строки string, изменяемые строки StringBuider и регулярные выражения Regex. В данном разделе мы рассмотрим работу с символами, неизменяемыми и изменяемыми строками.

 

Символы c har

Начнем с символов. Символьный тип char предназначен для хранения символа в кодировке Unicode. Символьный тип относится к встроенным типам данных С# и соответствует стандартному классу Сhar библиотеки .Net из пространства имен System. В этом классе определены статические методы, позволяющие задавать вид и категорию символа, а также преобразовывать символ в верхний или нижний регистр, в число. Рассмотрим основные методы:

 

Метод Описание
GetNumericValue Возвращает числовое значение символа, если он является цифрой, и -1 в противном случае.
GetUnicodeCategory Возвращаеткатегорию Unicode-символа. В Unicode символыразделенынакатегории, напримерцифры (DecimalDigitNumber), римскиецифры (LetterNumber), разделителистрок (LineSeparator), буквывнижнемрегистре (LowercaseLetter) ит.д.
IsControl Возвращает true, если символ является управляющим.
IsDigit Возвращает true, если символ является десятичной цифрой.
IsLetter Возвращает true, если символ является буквой.
IsLetterOrDigit Возвращает true, если символ является буквой или десятичной цифрой.
IsLower Возвращает true, если символ задан в нижнем регистре.
IsNumber Возвращает true, если символ является числом (десятичным или шестнадцатеричным).
IsPunctuation Возвращает true, если символ является знаком препинания.
IsSeparator Возвращает true, если символ является разделителем.
IsUpper Возвращает true, если символ задан в нижнем регистре.
IsWhiteSpace Возвращает true, если символ является пробельным (пробел, перевод строки, возврат каретки).
Parse Преобразует строку в символ (строка должна состоять из одного символа).
ToLower Преобразует символ в нижний регистр
ToUpper Преобразует символ в верхний регистр

Таблица 10.1

 

Нужен пример работы с символами. Вспомните, пожалуйста, консольный режим. Для экономии места и усилий работу с символами и со строками Мы(Вы) будем демонстрировать в теле метода Main.

 

static void Main()

{

char b = 'B', c = '\x64', d = '\uffff';

Console.WriteLine("{0}, {1}, {2}", b, c, d);

Console.WriteLine("{0}, {1}, {2}", char.ToLower(b), char.ToUpper(c), char.GetNumericValue(d));

chara;

do//цикл выполнятеся до тех пор, пока не ввели символ e

{

      Console.WriteLine("Введитесимвол: ");

      a = char.Parse(Console.ReadLine());

      Console.WriteLine("Введенсимвол {0}, егокод {1}, егокатегория {2}", a, (int)a, char.GetUnicodeCategory(a));

      if (char.IsLetter(a)) Console.WriteLine("Буква");

      if (char.IsUpper(a)) Console.WriteLine("Верхнийрегистр");

      if (char.IsLower(a)) Console.WriteLine("Нижнийрегистр");

      if (char.IsControl(a)) Console.WriteLine("Управляющийсимвол");

      if (char.IsNumber(a)) Console.WriteLine("Число");

      if (char.IsPunctuation(a)) Console.WriteLine("Разделитель");

}

while (a != 'e');

}

Пример 10.1

Рис.10.1

Используя символьный тип можно организовать массив символов и работать с ним на основе базового класса Array. Есть пример, но сомнения по объему.

 

Неизменяемые строки string

Тип string, предназначенный для работы со строками символов в кодировке Unicode, является встроенным типом С#. Каждый объект string - это неизменяемая последовательность символов Unicode, т.е. методы, предназначенные для изменения строк, возвращают измененные копиистроки, исходные же строки остаются неизменными.Оказывается, что благодаря этому ограничению строки в C# реализуются более эффективно. Хотя, на первый взгляд, такое ограничение кажется препятствием, на самом деле это не так. Когда требуется получить строку, отличающуюся от первоначальной, достаточно создать новую строку и «отказаться» от исходной. А поскольку ненужные объекты автоматически утилизируются средствами «сборщика мусора», то беспокоиться о дальнейшей судьбе «отвергнутых» строк не приходится.И ещё, надо подчеркнуть, что в C# строки это объекты, значит Мы(Вы) имеем дело со ссылочным типом и экземпляры типа stringследует инициировать (создать).Создать строку можно несколькими способами:

strings;                          // инициализация отложена

strings=”кол около колокола”;   //инициализация строковым литералом

strings=newstring (' ', 20);    //конструктор создает строку из 20 пробелов

intx = 12344556;                   //инициализировали целочисленную переменную

strings = x.ToString();     //преобразовали ее к типу string

char [] a={'a', 'b', 'c', 'd', 'e'}; //создали массив символов

stringv=newstring (a);       // создание строки из массива символов

stringv=newstring (a, 0, 2) //создание строки из частимассива символов,  при этом: 0 показывает с какого символа, 2 – сколько символов

//использовать для инициализации

 

Операции над строками

Над строками определены следующие операции:

· присваивание (=),

· две операции проверки эквивалентности (= =) и (!=),

· конкатенация или сцепление строк (+),

· взятие индекса ([]).

Обратите внимание, что в C# нет операций сравнения строк  типа« > », « < », которые широко используются в других языках программирования. Здесь для сравнения строк используются методы Compare.

 

Методы класса string

Класс string обладает богатым набором методов для сравнения строк, поиска в строке и других действий со строками. Рассмотрим эти методы.

 

Таблица 10.1

Название Вид Описание
static Compare Статический метод Сравнение двух строк в лексикографическом (алфавитном) порядке. Разные реализации метода позволяют сравнивать строки с учетом или без учета регистра.
CompareTo Экземплярныйметод Сравнение текущего экземпляра строки с другой строкой.
static Concat Статическийметод Слияние произвольного числа строк.
static Copy Статический метод Создание копии строки
static Empty Статическое поле Открытое статическое поле, представляющее пустую строку
static Format Статический метод Форматирование строки в соответствии с заданным форматом
IndexOf, IndexOfAny, LastIndexOf, LastIndexOfAny Экземплярные методы Определение индексов первого и последнего вхождения заданной подстроки или любого символа из заданного набора в данную строку.
Insert Экземплярный метод Вставка подстроки в заданную позицию
static Join Статический метод Слияние массива строк в единую строку. Между элементами массива вставляются разделители.
Length Свойство Возвращает длину строки
PadLeft, PadRigth Экземплярные методы Выравнивают строки по левому или правому краю путем вставки нужного числа пробелов в начале или в конце строки.
Remove Экземплярный метод Удаление подстроки из заданной позиции
Replace Экземплярный метод Замена всех вхождений заданной подстроки или символа новыми подстрокой или символом.
Split Экземплярный метод Разделяет строку на элементы, используя разные разделители. Результаты помещаются в массив строк.
StartWith, EndWith Экземплярные методы Возвращают true или false в зависимости от того, начинается или заканчивается строка заданной подстрокой.
Substring Экземплярный метод Выделение подстроки, начиная с заданной позиции
ToCharArray Экземплярный метод Преобразует строку в массив символов
ToLower, ToUpper Экземплярные методы Преобразование строки к нижнему или верхнему регистру
Trim, TrimStart, TrimEnd Экземплярные методы Удаление пробелов в начале и конце строки или только с одного ее конца.

 

Как говорилось выше, для сравнения строк в C# используется метод Compare, у которого есть несколько параметров, отвечающих за условия сравнения. Compare. Сравниваемые строки передаются этому методу в качестве параметров. Дополнительно методу Compare можно указывать, каким именно образом выполнять сравнение.

Если строки равны, метод Compare возвращает нулевое значение. Если первая строка меньше второй (используется лексикографическое сравнение), возвращается отрицательное значение, а если больше — положительное. А что значит одна строка больше другой? Как это понимать? Что значит сравнивать строки в лексикографическом порядке? При таком способе сравнения строки сравниваются посимвольно, поочередно, с начального до получения результата. А как сравниваются символы – по их кодам или номерам в таблице кодировок. Можно сказать проще – в соответствующем алфавите. Тот символ, у которого номер больше, тот и больше. Почему выбран именно такой способ сравнения? При таком способе отсортированные слова выстроятся в таком же порядке, как и во всех словарях, работающих с текстами.

Класс String содержит несколько перегруженных методов Compare. Прототип такого метода, предназначенного для лексикографического сравнения текстовых строк с учетом особенностей национального алфавита имеет вид:

public static int Compare(

Stringstringl,

Int32indexl,

String string2,

Int32 index2,

Int32 length,

BooleanignoreCase,

Culturelnfo culture);

 

Параметры stringl и indexl задают соответственно первую сравниваемую строку и позицию внутри ее с которой надо начинать сравнение.

Параметры string2 и index2 имеют то же назначение, относятся ко второй сравниваемой строке. Заметим, что параметры indexlи index2 можно не указывать. В этом случае происходит сравнение полных строк.

С помощью необязательного параметра length можно задать максимальную длину сравниваемых строк.

Если значение параметра ignoreCase равно true, то метод Compare не будет учитывать регистр сравниваемых строк.

Однако самый интересный параметр— culture. С его помощью можно указать функции национальный алфавит, который должен применяться для лексикографического сравнения строк.

Чтобы лексикографическое сравнение строк выполнялось правильно, необходимо учитывать особенности национальных алфавитов, использованных для представления строк.

Библиотека классов .NetFramework содержит специальный класс System.Globalization.CultureInfo, позволяющий задать национальный язык,или, в терминологии Microsoft.NETFramework, культуру (culture).

В табл. 10.2приведены имена и коды некоторых культур.

Таблица 10.2

Национальный язык Имя культуры
неучитывается "" (пустаястрока)
Английский en
Арабский ar
Белорусский be
Испанский es
Итальянский it
Немецкий de
Польский pl
Русский ru
Татарский tt
Узбекский yz
Узбекский (Узбекистан, кириллица) Cy-uz-UZ
Узбекский (Узбекистан, латиница) Lt-uz-UZ
Украинский uk
Французский fr

 

В примере 10.1 приведены варианты использования методов класса string.

namespace ConsoleApplication1

{

classProgram

{

 

staticvoidDelDubli(refstring s)

{// убирает лишние пробелы

// int i;

while (s.IndexOf(" ") >= 0)

       {//если находит два подряд идущие пробелы, то первый удаляет

s = s.Remove(s.IndexOf(" "), 1);

       }

   }

 

staticvoid Main(string[] args)

   {

string str1 = "Перваястрока";

string str2 = string.Copy(str1);

string str3 = "Вторая строка";

string str4 = "ВТОРАЯ строка";

stringstrUp, strLow;

int result, idx;

Console.WriteLine("str1: " + str1);

Console.WriteLine("Длинастроки str1: " + str1.Length);

Console.WriteLine("str2: " + str2);

Console.WriteLine("str3: " + str3);

Console.WriteLine("str4: " + str4);

/**/

// Создаем прописную и строчную версии строки str1.

strLow = str1.ToLower();

strUp = str1.ToUpper();

Console.WriteLine("Строчнаяверсиястроки str1: " + strLow);

Console.WriteLine("Прописнаяверсиястроки str1: " + strUp);

Console.WriteLine();

 

// Сравниваем две строки str1 с str3 НЕ ПОЛУЧАЕТСЯ !!!!!

//if (str1 > str3)

// Console.WriteLine(str1 + " > " + str3);

//else

// Console.WriteLine(str1 + " < " + str3);

       result = String.Compare(str1, str3);

Console.WriteLine("String.Compare(str1,str3):");

if (result == 0) Console.WriteLine("str1 и str3 равны.");

elseif (result < 0) Console.WriteLine("str1 меньше, чем str3");

elseConsole.WriteLine("str1 больше, чем str3");

Console.WriteLine();

 

 

// Сравниваем текущую строку str1 с str3,

result = str1.CompareTo(str3);

Console.WriteLine("str1.CompareTo(str3):");

if (result == 0) Console.WriteLine("str1 и str3 равны.");

elseif (result < 0) Console.WriteLine("str1 меньше, чем str3");

elseConsole.WriteLine("str1 больше, чем str3");

Console.WriteLine();

 

//сравниваемстрокибезучетарегистра

result = String.Compare(str3, str4, true);

Console.WriteLine("String.Compare(str3, str4, true):");

if (result == 0) Console.WriteLine("str3 и str4 равныбезучетарегистра.");

elseConsole.WriteLine("str3 и str4 неравныбезучетарегистра.");

Console.WriteLine();

 

//сравниваемчастистрок

       result = String.Compare(str1, 4, str2, 4, 2);//"ая" и "ая"

if (result == 0) Console.WriteLine("часть str1 и str2 равны");

elseConsole.WriteLine("часть str1 и str2 неравны");

Console.WriteLine();

//сравнение строк с учетом национальных особенностей (культуры)

str1="Вас";//кириллица

str2="Bac";//латиница

Console.WriteLine("Culture: " + str1 + " " + str2);

Console.WriteLine(String.Compare(str1, str2, true, newSystem.Globalization.CultureInfo("ru")));

Console.WriteLine(String.Compare(str1, str2, true, newSystem.Globalization.CultureInfo("en")));

// Поиск строк.

idx = str2.IndexOf("строка");

Console.WriteLine("Индекс первого вхождения подстроки строка: " + idx);

int idx1 = str2.IndexOf("строка",idx+1);

Console.WriteLine("Индекс вхождения подстроки строка после индекса "+idx+" = " + idx1);

idx = str2.LastIndexOf("о");

Console.WriteLine("Индекс последнего вхождения символа о: " + idx);

/**/

//конкатенация

stringstr = String.Concat(str1, str2, str3, str4);

Console.WriteLine("конкатенация "+str);

//удаление подстроки

str = str.Remove(0, str1.Length);

Console.WriteLine(str);

 

//замена подстроки "строка" на пустую подстроку

str = str.Replace("строка", "");

Console.WriteLine("замена:"+str);

 

charch = str[1];//читать из строку можно!!!

Console.WriteLine("символ строки:" + ch);

// str[1]='Ы';// в строке менять нельзя !!!

/**/

Console.ReadLine();

/**/

       {

stringpoems = "тучки небесные вечные     странники";

Console.WriteLine("Исходная строка для разбиения: " + poems);

// char[] div = { ' ' }; //создаем массив разделителей

// poems = poems.Replace(" ", " ");

DelDubli(ref poems);

// stringpoems = "тучки небесные, вечные странники...";

char[] div = { ' ', ',', '.'}; //создаем массив разделителей

Console.WriteLine("Подготовленная строка для разбиения: "+poems);

// Разбиваем строку на части,

string[] parts = poems.Split(div);

Console.WriteLine("Результат разбиения строки на части: ");

for (inti = 0; i<parts.Length; i++)

Console.WriteLine(parts[i]);

// Теперь собираем эти части в одну строку, в качестве разделителя используем символ |

string whole = String.Join(" | ", parts);

Console.WriteLine("Результатсборки: ");

Console.WriteLine(whole);

Console.ReadLine();

                   }

/*   */

   }

}

}

Пример 10.1

На Рис. 10.1 приведен результат работы программы из Примера 10.1

Рис.10.1. Результат работы программы примера 10.1.

Демонстрация работы методов класса String.

 

Изменяемые строкиStringBuilder

Чтобы создать строку, которую можно изменять, в С# предусмотрен класс StringBuilder, определенный в пространстве имен System.Text.  Этот тип более эффективно использует память, поэтому он применяется для работы со строками большого размера.

Объекты этого класса всегда объявляются с явным вызовом конструктора класса (через операцию new) . Примеры создания изменяемых строк:

StringBuilder a =newStringBuilder(); //создание пустой строки, размер по умолчанию 16 символов

 

//инициализация строки и выделение необходимой памяти

StringBuilderb = newStringBuilder("abcd");

 

//создание пустой строки и выделение памяти под 100 символов

StringBuilder с = newStringBuilder(100);

 

//инициализация строки и выделение памяти под 100 символов

StringBuilder d = new StringBuilder("abcd", 100);

 

//инициализация подстрокой "bcd", и выделение памяти под 100 символов        

StringBuilder d = new StringBuilder("abcd", 1, 3,100); 

 

Основные элементы класса приведены в таблице:

Название Вид Описание
Append Экземплярныйметод Добавление данных в конец строки. Разные варианты метода позволяют добавлять в строку величины любых встроенных типов, массивы символов, строки и подстроки string.
AppendFormat Экземплярный метод Добавление форматированной строки в конец строки
Capacity свойство Получение и установка емкости буфера. Если устанавливаемое значение меньше текущей длины строки или больше максимального, то генерируется исключение ArgumentOutOfRangeException
Insert Экземплярный метод Вставка подстроки в заданную позицию
Length изменяемое свойство Возвращает длину строки. Присвоение ему значения 0 сбрасывает содержимое и очищает строку
MaxCapacity неизменное свойство Возвращает наибольшее количество символов, которое может быть размещено в строке
Remove Экземплярныйметод Удаление подстроки из заданной позиции
Replace Экземплярный метод Замена всех вхождений заданной подстроки или символа новой подстрокой или символом
ToString Экземплярныйметод Преобразование в строку типа string
Chars изменяемоесвойство Возвращает из массива или устанавливает в массиве символ с заданным индексом. Вместо него можно пользоваться квадратными скобками []
Equals Экземплярныйметод Возвращает true, только если объекты имеют одну и ту же длину и состоят из одних и тех же символов
CopyTo Экземплярныйметод Копирует подмножество символов строки в массив char
Как видно, методы класса StringBuilder менее развиты, чем методы класса String, но они позволяют более эффективно использовать память за счет работы с изменяемыми строками. Рассмотрим примеры использования данных методов.

Лекция 11

Структуры

Структура – это тип языка C#, в котором под одним именем объединены несколько данных разных типов. Может показаться, что структура дублирует класс, только без методов, тем более, что к элементам структуры можно применять уровни доступа и у нее есть конструктор. С одной стороны это так, а с другой стороны возможно ине так. Дело в том, что этот тип может работать и как ссылочный тип (инициализация с помощью оператора new и с вызовом конструктора), и как значимый тип (без инициализации с помощью оператора new и без вызова конструктора). В чем разница. Первое – память под структурубудет захватываться в разных местах ОП. Если структура используется как значимый тип, то память захватывается в стеке и элементы не получают никаких значений. Здесь можно вспомнить такое сообщение при попытке компиляции как «Возможно использование неназначенного поля». Если же используется оператор new, то значения всех элементов структуры получают либо нулевые значения, либо пустые ссылки (null), либо значения заданные в конструкторе, который вызывается при инициализации. Кроме этого память при такой инициализации захватывается в области ОП, которая называется динамическая память. Стек и динамическая память – это разные места ОП. Они отличаются по объему, по способу доступа. Объем стека существенно меньше, но скорость доступа к нему выше, чем к динамической памяти. Объем динамической памяти – это, по сути, весь объем доступной ОП компьютера, но скорость доступа к ней меньше. Какой способ применить, зависит от задачи и от объема данных, с которыми планируется работать, используя структуры.

Ну а сейчас нужен пример работы со структурой. Ну допустим так: создадим структуру, в которой будут храниться сведения о студенте:фамилия, имя, отчество (ФИО), год рождения, пол. Представляется, что поля структуры Stud из примера 11.1 не требуют пояснений. В Main()-е приведены различные варианты работы с этой структурой.

 

ClassProgram

{

 

structStud

   {

publicstring FIO;

publicint gr;

publicchar sex;

   }

 

staticvoid Main(string[] args)

{

Studst; // структура без инициализации

st.FIO=»Вася»;

Console.WriteLine(«Без инициализации FIO=*»+st.FIO+»*»);

// Console.WriteLine(“*” + st.FIO+”*”+st.gr+”*”+st.sex);

//Ошибка компиляции «Использование поля gr, которому, возможно, не присвоено значение «

//Ошибка компиляции «Использование поля sex, которому, возможно, не присвоено значение «

Stud st1; //структура с инициализацией

       st1 = newStud();

Console.WriteLine(“Синициализацией FIO=*”+st1.FIO+”*”);

Console.WriteLine(“*” + st1.FIO+”*”+st1.gr+”*”+st1.sex+”*”);

 

Console.ReadLine();

   }

}

 

Пример 11.1. Работа со структурами.

 

 

 

Рис.11.1

Демонстрация работы со структурой.

 

 

Индексаторы

Индексатор это свойство (имеет get{} и set{}, см. лекцию 6, пункт 6.3 первой части пособия), но с параметрами, которые записываются в квадратных скобках. Наличие квадратных скобок делает работу с индексаторами похожей на работу с элементами массива. Это удобно, если данные в составе класса организованы или в виде массива, или в каком-либо другом виде, главное, чтобы обратиться к каждому элементу или вычислить его значение можно было с использованием этих самых параметров.

У индексатора должно быть имя this и никакого другого.

В чем отличие индексатора от свойства, которое отвечает за закрытое поле-массив. Соответствующее свойство оперирует с массивом как с единым целым (см. описание поля int[] masи свойства int[] Masиз пример 8.2). Очевидно, что это только «посредник» между закрытым полем и внешним миром и ни о каком контроле за значениями элементов массива говорить не приходится. В аксессорах же (напоминаем, что так называютсяметоды get{} и set{} свойства) индексатораможно организовать контроль за параметрами и значениями поля. Кроме этого, использование индексатора позволяет работать с любым объектом как с массивом, что бывает иногда просто удобнее.

В качестве примера использования индексатора напишем программку, в которой организуем класс с закрытым полем-массивом, а для доступа к массиву используем только индексатор с контролем и выявлением ошибок нарушения границ массива в нем. Единственным параметром индексатора будет индекс элемента массива.

namespace ConsoleApplication1

{

classMasIndthis

{

privateint[] a;//массив

publicint Length;//длинамассива

publicboolErrFl; //результат последней операции

 

publicMasIndthis(int size) // конструктор. Инициализациямассива

   { a = newint[size];

       Length = size;

}

Private bool Ok(intindex)// возвращает true если индекс в границах массива

{ boolfl;

if (index >= 0 && index < Length)

          fl=true;

else

           fl=false;

returnfl;

   }

 

]// это и есть индексатор класса MasIndthis

Public int this[int index]

   { get//акссесор

       { if (Ok(index))

           { ErrFl = false;

               return a[index];

           }

           else

           { ErrFl = true;

               Return int.MinValue;

           }

       }

       set

       { if (Ok(index))

           {

               ErrFl = false;

               a[index]=value;

           }

           else

           {

               ErrFl = true;

           }

       }

   }

}

 

classProgram

{

staticvoid Main(string[] args)

   {

MasIndthis mit = new MasIndthis(5);

Console.WriteLine("Скрытыйсбой");

for (inti = 0; i<mit.Length * 2; i++)

mit[i] = i * 10; // использованиеиндексатора(this[])

 

for (inti = 0; i<mit.Length * 2; i++)

Console.Write(mit[i] + " ");

Console.WriteLine();

Console.WriteLine("Сбой с уведомлением");

Console.WriteLine("Уведомление при формировании");

for (inti = 0; i<mit.Length * 2; i++)

{

mit[i] = i * 10; // использование индексатора(this[])

if (mit.ErrFl)

Console.WriteLine("a["+i+"]= внеграниц ");

}

Console.WriteLine("Уведомление при чтении");

for (inti = 0; i<mit.Length * 2; i++)

       {

int x=mit[i];

if (!mit.ErrFl)

Console.Write(x+" ");

else

Console.WriteLine("a[" + i + "]= внеграниц ");

}

Console.ReadLine();

   }

}

}

 

Пример 11.2

Рис.11.2. Результаты работы программы из примера 11.2.

Использование индексатора для работы с массивом

 

Код индексатора просит пояснений.

Индексатор начинается со строки

publicintthis[intindex].

 

public–это чтобы к индексаторы можно было обратиться извне;

int–тип элемента массива;

this[intindex] – служебноесловоthis. При обращении к индексатору это слово будет заменяться на имя текущего объекта; index– параметр индексатора.

В теле индексатора определены два аксессора. Акссесоры вызываются автоматически при использовании индексатора и оба получают параметрindex. Если индексатор стоит в левой части оператора присваивания, то вызывается аксессорset(), в иных случаях вызывается get().

Ну а проверка index-а на границы массива в индексаторе реализуется с использованием метода Ok(), ав поле ErrFl лежит результат последней операции с массивом в индексаторе. Кажется, что этих пояснений к примеру 11.2 достаточно.

Индексаторы можно перегружать. В этом случае они должны отличаться списком параметров. Далее, можно организовывать индексаторы с несколькими параметрами. Если в качестве параметров передать два индекса, то можно реализовать работу с двумерным массивом. Более того, иногда целесообразно использовать индексаторы даже в том случае, если данные даже не лежат в массиве, но в ним удобно обращаться как к элементам массива.

 

Тип var

С помощью оператора var можно создавать переменную без явного указания типа данных. А как узнать сколько памяти отводить под эту переменную? По контексту, то есть по значение, которое присваивается переменной при инициализации. Компилятор анализирует тип выражения справа от оператора присваивания и таким образом определяет тип переменной. В дальнейшем тип переменной изменить конечно же нельзя.

vara=10;

vars=”строка”;

varv[] = {10,20,30};

 

Кажется, что в программировании такое уже было. В языках типа Basic можно было вообще не описывать переменные. Их типы определялись при первом использование переменной в программе, а это, конечно же, присваивание.

Увлекаться таким типом не надо.

Однако хорошим примером может служить использование переменной типа varв перечислении.

foreach (var x in массив)

x.ToString;

Шаблоны

Шаблоны – это очень мощное средство, которое спасает программистов от написания бессмысленного кода в случае, когда надо выполнять одни и те же операции над разными типами данных. Рассмотрим пример,в котором создадим шаблон простого метода.

Static string sum<T>(T value1, T value2)

{

return value1.ToString() + value2.ToString();

}

 

Поясним: static string sum это как в обычном методе. А дальше в треугольных скобках пишется какая-нибудь строка. Как правило используется буква <T>. При вызове этого метода с треугольных скобках вместо T будет записан тот тип данных, который будет использоваться в работе метода. Далее в описании метода в круглых скобках пишутся параметрыс использованием какого-то типа T, который будет определен на этапевызова метода.

Почему T ? Скорее всего от английского Template (шаблон). В принципе можно и по-другому, но так уж принято.

Использование этого метода демонстрируется в примере 11.3.

 

namespaceTemplateProject2

{

Class Program

{

staticvoid Main(string[] args)

   {

String int sum = sum<int>(10, 20);

Console.WriteLine(intsum);

 

String str sum = sum<string>("Hello ", "world");

Console.WriteLine(strsum);

 

Console.ReadLine();

   }

 

staticstring sum<T>(T value1, T value2)

   {

return value1.ToString() + value2.ToString();

}

}

}

Пример 11.3.

Поясняем. Первый раз метода вызывается как sum<int>.В треугольных скобках указан типint. Значит в шаблоне везде, где была буква T будет подразумеваться тип int. Потому качестве параметров в метод передаются числа. Во второй раз метод вызывается как sum<string>, указывая в качестве шаблона типstring. Соответственно, фактические параметры метода в этом случае должны быть типаstring.Если параметры будут другими, то произойдет ошибка.

 

Рис.11.3. Результат работы программы из примера 11.3.

Использование шаблона в методе.

Мощь шаблонов более наглядна видна на классах. В примере 11.4 написан класс TemplateTest для работы со статическим массивом. За счет шаблонов использование этого класса становится универсальным.

При объявлении класса, использующего шаблон, буква шаблона указывается в треугольных скобках после имени класса. Теперь внутри класса букву T следует воспринимать как тип данных – объявлять переменные, получать параметры, возвращать значения типа T. При инициализации объекта класса TemplateTestследует указать с каким типом данных будет работать объект.

namespaceTemplateProject

{

Public class TemplateTest<T>

{

   T[] array = new T[10];

int index = 0;

 

publicbool Add(T value)

   {

if (index >= 10)

return false;

 

       array[index++] = value;

return true;

   }

 

public T Get(int index)

   {

if (index <this.index&& index >=0 )

return array[index];

else

return default(T);

   }

 

publicint Count()

   {

return index;

}

}

 

publicstaticclassClass1

{

staticvoid Main()

   {

TemplateTest<int>testarray = newTemplateTest<int>();

 

testarray.Add(10);

testarray.Add(1);

testarray.Add(3);

testarray.Add(14);

 

for (inti = 0; i<testarray.Count(); i++)

       {

Console.WriteLine(testarray.Get(i));

}

Console.ReadLine();

   }

}

 

 

}

Пример 11.4

 

Рис. 11.4. Результат работы программы из примера 11.4.

Использование шаблона в классе.

 

Для того, чтобы создать такой же массив из строк, достаточно изменить объявление

TemplateTest<string>testarray = newTemplateTest<string>();

 

Получаетчто, писать новый класс, который будет делать тоже, но для данных типа stringне надо. Благодаря шаблону все уже готово!

Условная компиляция

Условная компиляция – это процесс, в котором условные конструкции препроцессора позволяют компилировать или пропускать часть программы в зависимости от выполнения некоторого условия. Т.е. простыми словами перед компиляцией наш файл может подставлять нужный нам вариант кода.

Например:
Пусть у нас есть такое простейшее консольное приложение

 

  usingSystem;   namespaceConsoleApplication1 { classProgram { staticvoidMain(string[] args) { Console.WriteLine("this is standard version configuration"); Console.Read(); } } }

И нам необходимо сделать версию программы, в которой будет меняться только вывод сообщения, для этого добавляем определение имени через директиву #define и добавляем директивы условия#if #else #endif

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #define SpecialVersion usingSystem;   namespaceConsoleApplication1 { classProgram { staticvoidMain(string[] args) { #if SpecialVersion Console.WriteLine("this is special version cofiguration"); #else Console.WriteLine("this is standard version cofiguration"); #endif Console.Read(); } } }

В данном случае у нас внутри функции Main скомпилируется только код

1 2 Console.WriteLine("this is special version cofiguration"); Console.Read();

Т.е. итоговый код, который будет компилироваться получится таким:

1 2 3 4 5 6 7 8 9 10 11 12 13 usingSystem;   namespaceConsoleApplication1 { classProgram { staticvoidMain(string[] args) { Console.WriteLine("this is special version cofiguration"); Console.Read(); } } }

Если необходимо применить имя условия в рамках всего проекта, то в свойствах проекта укажите имя области в текстовом поле Conditionalcompilationsymbols (Символы условной компиляции), расположенным на вкладке Построение(Build) подпунктаСвойства (Properties)пункта Проект (Build) главного меню проекта:

 

Рис.11.5. Установка директивы условной компиляции в свойствах проекта.

 

Если мы указываем имя условия в свойстве проекта, то в коде программы определять имена через директивы #define не надо.



Лекция 12

Потоки. Текстовые файлы

 

 

Лекция 13

Платформа .NET

Теперь об этом можно поговорить!

Приложение 1.

(Первое лабораторное занятие второго семестра)

Третья часть пособия.

Полиморфизм.

Абстрактные методы.

Интерфейсы.

Делегаты. События.

Графика.

Приложение 2.

Информационные технологии. Язык программирования C#.

Дата: 2019-11-01, просмотров: 158.