Главная страница
Навигация по странице:

  • Практическая работа №13

  • Проверка на соответствие строки формату

  • Практическая работа №14

  • Практическая работа №15

  • Композиция Композиция определяет отношение HAS A

  • Агрегация От композиции следует отличать агрегацию. Она также предполагает отношение HAS A

  • Методические рекомендации по выполнению практических работ по междисциплинарному курсу


    Скачать 2.6 Mb.
    НазваниеМетодические рекомендации по выполнению практических работ по междисциплинарному курсу
    Дата05.09.2022
    Размер2.6 Mb.
    Формат файлаpdf
    Имя файлаMU_PR_MDK_01_01.pdf
    ТипМетодические рекомендации
    #663423
    страница6 из 13
    1   2   3   4   5   6   7   8   9   ...   13

    Stack
    Открытые конструкторы
    Stack
    Перегружен. Инициализирует новый экземпляр класса Stack
    Открытые свойства
    Count
    Возвращает число элементов, которое хранится в классе Stack
    IsSynchronized
    Возвращает значение, определяющее, является ли доступ к классу Stack синхронизированным (потокобезопасным)
    SyncRoot
    Возвращает объект, который может быть использован для синхронизации доступа к классу Stack
    Открытые методы
    Clear
    Удаляет все объекты из класса Stack
    Clone
    Создает неполную копию класса Stack
    Contains
    Определяет, принадлежит ли элемент классу Stack
    CopyTo
    Копирует элементы класса Stack в существующий одномерный массив класса Array, начиная с указанного индекса массива
    GetEnumerator Интерфейс IEnumerator для класса Stack
    Peek
    Возвращает самый верхний объект класса Stack, но не удаляет его
    Pop
    Удаляет и возвращает верхний объект класса Stack
    Push
    Вставляет объект в начало класса Stack
    Synchronized Возвращает синхронизированную (потокобезопасную) обертку класса Stack
    ToArray
    Копирует элементы класса Stack в новый массив
    Класс Stack допускает в качестве действительного значение "пустая ссылка", а также допускает наличие повторяющихся элементов.
    Ниже приведен пример создания и инициализации класса Stack и способ вывода его значений: using System; using System.Collections; public class SamplesStack { public static void Main()
    {
    // Creates and initializes a new Stack.
    Stack myStack = new Stack(); myStack.Push("Hello"); myStack.Push("world"); myStack.Push("!");

    // Displays the properties and values of the Stack.
    Console.WriteLine( "myStack" );
    Console.WriteLine( "\tCount: {0}", myStack.Count );
    Console.Write( "\tValues:" );
    PrintValues( myStack );
    } public static void PrintValues( IEnumerable myCollection )
    {
    System.Collections.IEnumerator myEnumerator = myCollection.GetEnumerator(); while ( myEnumerator.MoveNext() )
    Console.Write( "\t{0}", myEnumerator.Current );
    Console.WriteLine();
    }
    }
    Листинг 12.5.
    Результат: myStack
    Count: 3
    Values: ! world Hello
    Перечислитель
    Наследует интерфейс IEnumerator, который является основным для всех перечислителей.
    Поддерживает простое перемещение по коллекции.
    Открытые свойства
    Current
    Возвращает текущий элемент коллекции
    Открытые методы
    MoveNext
    Перемещает перечислитель на следующий элемент коллекции
    Reset
    Устанавливает перечислитель в исходное положение перед первым элементом коллекции
    Перечислитель позволяет считывать (только считывать!) информацию (данные) из коллекции. Перечислители не используются для изменения содержания коллекции. Для этого применяются специфические методы данной коллекции ( Enqueue, Dequeue, Push,
    Pop ).
    Вновь созданный перечислитель размещается перед первым элементом коллекции.
    Метод Reset возвращает перечислитель обратно в положение перед первым элементом коллекции.
    В этом положении обращение к свойству Current приводит к возникновению исключения.
    Поэтому необходимо вызвать метод MoveNext, чтобы переместить перечислитель на первый элемент коллекции до считывания значения свойства Current.
    Свойство Current не меняет своего значения (возвращает ссылку на один и тот же член коллекции), пока не будет вызван метод MoveNext или Reset.
    Метод MoveNext обеспечивает изменение значения свойства Current.
    Завершение перемещения по коллекции приводит к установке перечислителя после последнего элемента коллекции.
    При этом вызов
    метода MoveNext возвращает значение false.
    Если последний вызов
    метода MoveNext вернул значение false, обращение к свойству Current приводит к возникновению исключения.
    Последовательный вызов методов Reset и MoveNext приводит к перемещению перечислителя на первый элемент коллекции.

    Перечислитель действителен до тех пор, пока в коллекцию не вносятся изменения. Если в коллекцию вносятся изменения (добавляются или удаляются элементы коллекции), перечислитель становится недействительным, а следующий вызов методов MoveNext или Reset приводит к возникновению исключения InvalidOperationException.
    После изменения коллекции в промежутке между вызовом метода MoveNext и новым обращением к свойству Current, свойство Current возвращает текущий элемент коллекции, даже если перечислитель уже недействителен.
    Перечислитель не имеет монопольного доступа к коллекции, поэтому перечисление в коллекции не является потокобезопасной операцией. Даже при синхронизации коллекции другие потоки могут изменить ее, что приводит к созданию исключения при перечислении. Чтобы обеспечить потокобезопасность при перечислении, можно либо заблокировать коллекцию на все время перечисления, либо перехватывать исключения, которые возникают в результате изменений, внесенных другими потоками.

    Практическая работа №13 Использование регулярных выражений
    Синтаксис регулярных выражений
    Рассмотрим вкратце некоторые элементы синтаксиса регулярных выражений:

    ^: соответствие должно начинаться в начале строки
    (например, выражение @"^пр\w*" соответствует слову "привет" в строке "привет мир")

    $: конец строки (например, выражение @"\w*ир$" соответствует слову "мир" в строке "привет мир", так как часть "ир" находится в самом конце)

    .: знак точки определяет любой одиночный символ
    (например, выражение "м.р" соответствует слову "мир" или "мор")

    *: предыдущий символ повторяется 0 и более раз

    +: предыдущий символ повторяется 1 и более раз

    ?: предыдущий символ повторяется 0 или 1 раз

    \s: соответствует любому пробельному символу

    \S: соответствует любому символу, не являющемуся пробелом

    \w: соответствует любому алфавитно-цифровому символу

    \W: соответствует любому не алфавитно-цифровому символу

    \d: соответствует любой десятичной цифре

    \D : соответствует любому символу, не являющемуся десятичной цифрой
    Это только небольшая часть элементов. Более подробное описание синтаксиса регулярных выражений можно найти на msdn в статье Элементы языка регулярных выражений — краткий справочник.
    Теперь посмотрим на некоторые примеры использования. Возьмем первый пример с скороговоркой "Бык тупогуб, тупогубенький бычок, у быка губа бела была тупа" и найдем в ней все слова, где встречается корень "губ":
    1 2 string s = "Бык тупогуб, тупогубенький бычок, у быка губа бела была тупа";
    Regex regex = new Regex(@"\w*губ\w*");
    Так как выражение \w* соответствует любой последовательности алфавитно-цифровых символов любой длины, то данное выражение найдет все слова, содержащие корень "губ".
    Второй простенький пример - нахождение телефонного номера в формате 111-111-1111:
    1 2 string s = "456-435-2318";
    Regex regex = new Regex(@"\d{3}-\d{3}-\d{4}");
    Если мы точно знаем, сколько определенных символов должно быть, то мы можем явным образом указать их количество в фигурных скобках: \d{3} - то есть в данном случае три цифры.
    Мы можем не только задать поиск по определенным типам символов - пробелы, цифры, но и задать конкретные символы, которые должны входить в регулярное выражение.
    Например, перепишем пример с номером телефона и явно укажем, какие символы там должны быть:
    1 2 string s = "456-435-2318";
    Regex regex = new Regex("[0-9]{3}-[0-9]{3}-[0-9]{4}");
    В квадратных скобках задается диапазон символов, которые должны в данном месте встречаться. В итоге данный и предыдущий шаблоны телефонного номера будут эквивалентны.
    Также можно задать диапазон для алфавитных символов: Regex regex = new Regex("[a- v]{5}"); - данное выражение будет соответствовать любому сочетанию пяти символов, в котором все символы находятся в диапазоне от a до v.
    Можно также указать отдельные значения: Regex regex = new Regex(@"[2]*-[0-9]{3}-
    \d{4}");. Это выражение будет соответствовать, например, такому номеру телефона "222-
    222-2222" (так как первые числа двойки)
    С помощью операции | можно задать альтернативные символы: Regex regex = new
    Regex(@"[2\|3]{3}-[0-9]{3}-\d{4}");. То есть первые три цифры могут содержать только двойки или тройки. Такой шаблон будет соответствовать, например, строкам "222-222-

    2222" и "323-435-2318". А вот строка "235-435-2318" уже не подпадает под шаблон, так как одной из трех первых цифр является цифра 5.
    Итак, у нас такие символы, как *, + и ряд других используются в качестве специальных символов. И возникает вопрос, а что делать, если нам надо найти, строки, где содержится точка, звездочка или какой-то другой специальный символ? В этом случае нам надо просто экранировать эти символы слешем:
    1 2
    Regex regex = new Regex(@"[2\|3]{3}\.[0-9]{3}\.\d{4}");
    // этому выражению будет соответствовать строка "222.222.2222"
    Проверка на соответствие строки формату
    Нередко возникает задача проверить корректность данных, введенных пользователем. Это может быть проверка электронного адреса, номера телефона, Класс Regex предоставляет статический метод IsMatch, который позволяет проверить входную строку с шаблоном на соответствие:
    1 2
    3 4
    5 6
    7 8
    9 10 11 12 13 14 15 16 17 string pattern = @"^(?("")(""[^""]+?""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|

    \w])*)(?<=[0-9a-z])@))" +
    @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9]{2,17}))$"; while (true)
    {
    Console.WriteLine("Введите адрес электронной почты"); string email = Console.ReadLine(); if (Regex.IsMatch(email, pattern, RegexOptions.IgnoreCase))
    {
    Console.WriteLine("Email подтвержден"); break;
    } else
    {
    Console.WriteLine("Некорректный email");
    }
    }
    Переменная pattern задает регулярное выражение для проверки адреса электронной почты.
    Данное выражение предлагает нам Microsoft на страницах msdn.
    Для проверки соответствия строки шаблону используется метод
    IsMatch: Regex.IsMatch(email, pattern, RegexOptions.IgnoreCase). Последний параметр указывает, что регистр можно игнорировать. И если введенная строка соответствует шаблону, то метод возвращает true.
    Замена и метод Replace
    Класс Regex имеет метод Replace, который позволяет заменить строку, соответствующую регулярному выражению, другой строкой:
    1 2
    3 4
    5 string s = "Мама мыла раму. "; string pattern = @"\s+"; string target = " ";
    Regex regex = new Regex(pattern); string result = regex.Replace(s, target);
    Данная версия метода Replace принимает два параметра: строку с текстом, где надо выполнить замену, и сама строка замены. Так как в качестве шаблона выбрано выражение "\s+ (то есть наличие одного и более пробелов), метод Replace проходит по всему тексту и заменяет несколько подряд идущих пробелов ординарными.
    Практическая работа №14 Операции со списками
    Класс List из пространства имен System.Collections.Generic представляет простейший список однотипных объектов.

    Среди его методов можно выделить следующие:

    void Add(T item): добавление нового элемента в список

    void AddRange(ICollection collection): добавление в список коллекции или массива

    int BinarySearch(T item): бинарный поиск элемента в списке. Если элемент найден, то метод возвращает индекс этого элемента в коллекции. При этом список должен быть отсортирован.

    int IndexOf(T item): возвращает индекс первого вхождения элемента в списке

    void Insert(int index, T item): вставляет элемент item в списке на позицию index

    bool Remove(T item): удаляет элемент item из списка, и если удаление прошло успешно, то возвращает true

    void RemoveAt(int index): удаление элемента по указанному индексу index

    void Sort(): сортировка списка
    Посмотрим реализацию списка на примере:
    1 2
    3 4
    5 6
    7 8
    9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 using System; using System.Collections.Generic; namespace Collections
    { class Program
    { static void Main(string[] args)
    {
    List numbers = new List() { 1, 2, 3, 45 }; numbers.Add(6); // добавление элемента numbers.AddRange(new int[] { 7, 8, 9 }); numbers.Insert(0, 666); // вставляем на первое место в списке число 666 numbers.RemoveAt(1); // удаляем второй элемент foreach (int i in numbers)
    {
    Console.WriteLine(i);
    }
    List people = new List
    (3); people.Add(new Person() { Name = "Том" }); people.Add(new Person() { Name = "Билл" }); foreach (Person p in people)
    {
    Console.WriteLine(p.Name);
    }
    Console.ReadLine();
    }
    } class Person
    { public string Name { get; set; }

    40 41
    }
    }
    Здесь у нас создаются два списка: один для объектов типа int, а другой - для объектов Person. В первом случае мы выполняем начальную инициализацию списка: List numbers = new List() { 1, 2, 3, 45 };
    Во втором случае мы используем другой конструктор, в который передаем начальную емкость списка: List people = new List
    (3);. Указание начальной емкости списка (capacity) позволяет в будущем увеличить производительность и уменьшить издержки на выделение памяти при добавлении элементов. Также начальную емкость можно установить с помощью свойства Capacity, которое имеется у класса List.

    Практическая работа №15 Использование основных шаблонов можем выделить несколько основных отношений: наследование, реализация, ассоциация, композиция и агрегация.
    Наследование
    Наследование является базовым принципом ООП и позволяет одному классу (наследнику) унаследовать функционал другого класса (родительского). Нередко отношения наследования еще называют генерализацией или обобщением. Наследование определяет отношение IS A, то есть "является". Например:
    1 2
    3 4
    5 6
    7 8
    9 10 class User
    { public int Id { get; set; } public string Name { get; set; }
    } class Manager : User
    { public string Company{ get; set; }
    }
    В данном случае используется наследование, а объекты класса Manager также являются и объектами класса User.
    С помощью диаграмм UML отношение между классами выражается в незакрашенной стрелочке от класса-наследника к классу-родителю:
    Реализация
    Реализация предполагает определение интерфейса и его реализация в классах. Например, имеется интерфейс IMovable с методом Move, который реализуется в классе Car:
    1 2
    3 4
    5 6
    7 8
    9 10 11 public interface IMovable
    { void Move();
    } public class Car : IMovable
    { public void Move()
    {
    Console.WriteLine("Машина едет");
    }
    }
    С помощью диаграмм UML отношение реализации также выражается в незакрашенной стрелочке от класса к интерфейсу, только линия теперь пунктирная:
    Ассоциация
    Ассоциация - это отношение, при котором объекты одного типа неким образом связаны с объектами другого типа. Например, объект одного типа содержит или использует объект другого типа. Например, игрок играет в определенной команде:
    1 2
    3 4
    5 6
    7 class Team
    {
    } class Player
    { public Team Team { get; set; }

    8
    }
    Класс Player связан отношением ассоциации с класом Team. На схемах UML ассоциация обозначается в виде обычно стрелки:
    Нередко при отношении ассоциации указывается кратность связей. В данном случае единица у Team и звездочка у Player на диаграмме отражает связь 1 ко многим. То есть одна команда будет соответствовать многим игрокам.
    Агрегация и композиция являются частными случаями ассоциации.
    Композиция
    Композиция определяет отношение HAS A, то есть отношение "имеет". Например, в класс автомобиля содержит объект класса электрического двигателя:
    1 2
    3 4
    5 6
    7 8
    9 10 11 public class ElectricEngine
    { } public class Car
    {
    ElectricEngine engine; public Car()
    { engine = new ElectricEngine();
    }
    }
    При этом класс автомобиля полностью управляет жизненным циклом объекта двигателя.
    При уничтожении объекта автомобиля в области памяти вместе с ним будет уничтожен и объект двигателя. И в этом плане объект автомобиля является главным, а объект двигателя - зависимой.
    На диаграммах UML отношение композиции проявляется в обычной стрелке от главной сущности к зависимой, при этом со стороны главной сущности, которая содержит, объект второй сущности, располагается закрашенный ромбик:
    Агрегация
    От композиции следует отличать агрегацию. Она также предполагает отношение HAS A, но реализуется она иначе:
    1 2
    3 4
    5 6
    7 8
    9 10 11 public abstract class Engine
    { } public class Car
    {
    Engine engine; public Car(Engine eng)
    { engine = eng;
    }
    }
    При агрегации реализуется слабая связь, то есть в данном случае объекты Car и Engine будут равноправны. В конструктор Car передается ссылка на уже имеющийся объект
    Engine. И, как правило, определяется ссылка не на конкретный класс, а на абстрактный класс или интерфейс, что увеличивает гибкость программы.
    Отношение агрегации на диаграммах UML отображается также, как и отношение композиции, только теперь ромбик будет незакрашенным:

    При проектировании отношений между классами надо учитывать некоторые общие рекомендации. В частности, вместо наследования следует предпочитать композицию. При наследовании весь функционал класса-наследника жестко определен на этапе компиляции. И во время выполнения программы мы не можем его динамически переопределить. А класс-наследник не всегда может переопределить код, который определен в родительском классе. Композиция же позволяет динамически определять поведение объекта во время выполнения, и поэтому является более гибкой.
    Вместо композиции следует предпочитать агрегацию, как более гибкий способ связи компонентов. В то же время не всегда агрегация уместна. Например, у нас есть класс человека, который содержит объект нервной системы. Понятно, что в реальности, по крайней мере на текущий момент, невозможно вовне определить нервную систему и внедрить ее в человека. То есть в данном случае человек будет главным компонентом, а нервная система - зависимым, подчиненным, и их создание и жизненный цикл будет происходить совместно, поэтому здесь лучше выбрать композицию.
    1   2   3   4   5   6   7   8   9   ...   13


    написать администратору сайта