Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование. Введение в разработку на C#. Учебное пособие
.pdf
программы и многое другое. Наличие полноценной поддержки
обобщенных типов на уровне IL-кода позволило .NET вырваться вперед
в конкуренции с платформой Java.
14.2. Лямбда-функции
Лямбда-функции (англ. lambda) – это особый вид функций, не имею-
щих имени и объявляемых по месту их выполнения. Существует целый
раздел в математике, посвященный лямбда-счислению, однако в контексте
этой главы важным является вышеобозначенное определение.
Лямбда-функции в .NET представляют собой процедуры, которые
не привязаны ни к одному из типов. Они могут вызываться в любом
контексте, а также в их теле можно обращаться к любым переменным,
которые объявлены вне тела lambda-функции. Такое поведение
называется замыканием. Оно является мощным инструментом
связывания контекста и действия.
Вышеописанные функции делятся на две группы: Действия
(Actions) и Преобразования (Funcs), которые, соответственно,
различаются отсутствием и наличием возвращаемого значения. В языке
.NET определены следующие типы для обозначения лямбда-функций:
Action<TIn>, Action<TIn, TIn2>, Action<TIn, TIn2, TIn3>,
Func<TIn>, Func<TIn, TOut>, Func<TIn, TOut1, TOut2>.
In, Out – типы входных и выходных аргументов. Как видно из
объявлений, Func всегда определяет выходное значение и произвольное
количество входных, а Action определяет лишь входные типы. Пример:
Func<int, int> f = (x) => x+2;
Action<Func<int, int>, int> a = (x, y) =>
Debug.WriteLine(x(y));
f2(f, 4); // 6.
int i = 5;
Func<int, int> f2 = (x) => x+i;
f2(5); // 10.
101

Как видно, такие функции объявляются при помощи скобок, в
которые передаются параметры. Если параметров нет, то скобки пусты.
Также используется символ «жирной стрелки», который читается как
«переходит в». После жирной стрелки идет выражение, определяющее
функцию. Если нет фигурных скобок, то return не нужен, однако при их
наличии необходимо традиционным способом явно указать, что
является выходным значением.
14.3. LINQ
LINQ – аббревиатура, скрывающая мощный инструмент преобразования коллекций и выборки элементов. Это еще одна технология, которая
позволила .NET занять лидирующие позиции в корпоративном секторе
разработки приложений и потеснить Java. Неудивительно, что работа с
массивами – самая востребованная операция в языках программирования,
ибо без нее не было бы причин изобретать компьютер.
LINQ позволяет выполнять действия над массивами без явного
использования циклов и последовательных обработчиков, записывая
цепочки вызовов, как если бы операции шли друг за другом. Однако в
общем виде, LINQ – это не только обработка массивов, которые
находятся в памяти. Это абстрактный слой доступа к коллекциям
посредством универсальных провайдеров данных: например,
существуют LINQ-провайдеры, подключающиеся к магазину Amazon и
представляющие его в виде одной большой коллекции товаров. Также
существуют LINQ-провайдеры и для СУБД. Однако в рамках текущей
статьи будет рассмотрена самая простая разновидность LINQ: LINQ To
Objects. Пример:
new List<int>{3,2,1}.OrderBy(x => x); // 1, 2, 3
new List<int>{3,2,1}.Where(x => x > 2).Select(x => x *
x); // 9
Как вы уже догадались, LINQ использует лямбда-выражения и шаб-
лонные типы для цепочек действий над данными, записываемые деклара-
102

тивным наглядным образом. Заметьте, что преобразования не затрагивают
исходную коллекцию, она остается неизменной. Вместо коллекций могут
быть любые объекты, сложные структуры данных или строки.
14.4. Вопросы для самопроверки
1. Дайте определение шаблонным типам, лямбда-функциям и LINQ.
2. Для каких целей создавались шаблонные типы?
3. На какие две группы делятся лямбда-функции?
4. Для каких целей создавался LINQ?
5. Позволяет ли LINQ представлять в виде коллекций Web-сайты,
базы данных? Что необходимо для этого?
6. Какие главные преимущества .NET перед платформой Java рас-
смотрены в данной главе?
14.5. Задания для самопроверки
1. Приведите примеры данных в предметной области института,
требующих представления в виде шаблонных типов.
2. С помощью lambda-функций докажите, что любую функцию с
двумя аргументами можно привести к виду функции с одним
свободным аргументом и другим зафиксированным определенным
значением. По-научному это называется «каррирование». Подумайте,
как использовать полученный эффект на практике.
3. С помощью LINQ решите любые три задачи, встречавшиеся в
вашей практике и требовавшие использования циклов.
103

15. РАБОТА С ФАЙЛАМИ
15.1. Краткие теоретические сведения
Для создания файла можно воспользоваться классом FileInfo из
пространства имен System.IO. В конструктор передаётся имя будущего
файла. Создание файла производится вызовом метода Create():
FileInfo fi = new FileInfo("new.txt");
fi.Create();
Для удаления файла используется метод Delete():
FileInfo fi = new FileInfo("new.txt");
fi.Delete();
Для записи в файл (а также для чтения) используются символьные
потоки, позволяющие оперировать непосредственно с символами
Unicode:
StreamWriter sw = new StreamWriter("name.txt");
sw.WriteLine("текст");
sw.Close();
После всех действий над файлом нужно закрывать его при помощи
метода Close(), в противном случае изменения в файле не будут
сохранены. Приведённый выше пример записи файла полностью
перезаписывает его. Если же надо дописать информацию в конец файла,
это можно сделать следующим образом:
StreamWriter sw;
FileInfo fi = new FileInfo("name.txt");
sw = fi.AppendText();
sw.WriteLine("текст");
sw.Close();
104

Для того чтобы файл был корректно считан, он должен быть
сохранен в юникоде:
StreamReader streamReader = new StreamReader("name.txt");
string str = "";
while (!streamReader.EndOfStream)
{
str += streamReader.ReadLine();
}
15.2. Вопросы для самопроверки
1. Какой класс используется для операций над файлом? Назовите
его основные методы и их предназначение.
2. Что необходимо сделать, чтобы выполнить запись в конец файла?
3. Какую операцию необходимо совершать последней? Что
произойдет с данными, отправленными в файл, если ее не выполнить?
15.3. Задания для самопроверки
1. Добавьте в существующее решение заданий 2-3 раздела 13 возможность сохранения справочника на диск и последующего чтения с
диска.
2. Напишите программу, которая может считать простые числа методом решета Эратосфена в произвольном диапазоне, а результат записывать в текстовый файл в виде списка чисел. Числа разделены с помощью "\n".
105

16. ПРАВИЛА НАПИСАНИЯ КОДА. ПРАВИЛА ИМЕНОВАНИЯ
16.1. Краткие теоретические сведения
При написании кода важно придерживаться общих для всех
разработчиков правил именования и форматирования. В первую
очередь, по той причине, что код чаще читается, чем пишется, и помимо
разработчика, его может читать множество других людей.
Общие правила именования языковых конструкций:
1) Не экономьте на понятности и чистоте кода ради скорости
набора. Главное, чтобы смысл идентификатора был понятен в
используемом контексте. Например, количество элементов
лучше назвать Count, а не CountOfElementsInMyCollection;
2) Не используйте подчеркивание для отделения слов внутри
идентификаторов, это удлиняет идентификаторы и затрудняет
чтение. Вместо этого используйте стиль именования Кемел или
Паскаль (см. ниже).
В языке С# принято использовать два стиля использования регистра.
Паскаль – указание этого стиля оформления идентификатора
обозначает, что первая буква заглавная и все последующие первые
буквы слов тоже заглавные. Например, BackColor, LastModified,
DateTime.
Кэмел – указание этого стиля обозначает, что первая буква
строчная, а остальные первые буквы слов заглавные. Например,
borderColor, accessTime, templateName.
16.2. Выбор названий
Пространства имен:
1) для пространства имен используйте имя компании, затем
название продукта и, возможно, название подсистемы или
существенной части проекта. Например, SamGTU.Framework,
SamGTU.MegaTool.Scanner;
106

2) используйте стиль Паскаль для регистра букв.
Примеры:
namespace SamGTU.Collections {}
namespace SamGTU.Common {}
Классы/Структуры:
1) используйте существительное (одно или несколько
прилагательных и существительное) для имени класса;
2) используйте стиль Паскаль для регистра букв.
Интерфейсы:
1) используйте описывающее существительное прилагательное
(или одно или несколько прилагательных и существительное)
для идентификатора интерфейса. Например, IComponent – это
описывающее существительное, ICustomAttributeProvider – это
конкретизированное прилагательными существительное, а
IPersistable – это характеризующее прилагательное;
2) используйте стиль Паскаль для регистра букв;
3) используйте префикс I (заглавная i) для интерфейсов, чтобы
уточнить, что тип является интерфейсом. Старайтесь избегать
интерфейсов с двумя I в начале, например IIdentifiable.
Попробуйте подобрать синоним, например IRecognizable.
Примеры:
public interface IComponent
{
// Объявление интерфейса
}
public class Component : Icomponent
{
// Реализация интерфейса
}
Перечисления:
1) используйте стиль Паскаль для регистра букв в названии и
значениях перечисления.
107

Пример:
public enum CodeStyle
{
Good,
Normal,
Bad,
Ugly
}
Поля:
1) публичные поля (private, protected и protected internal)
именуются в стиле Кэмел и начинаются с префикса _;
2) публичные поля именуются в соответствии с правилами
именования свойств.
Методы:
1) используйте глаголы или комбинацию глагола и
существительных и прилагательных для имен методов;
2) используйте стиль Паскаль для регистра букв (вне зависимости
от области видимости метода).
Примеры:
private int RemoveAll() {}
public void GetCharArray() {}
Свойства:
1) используйте существительное или одно или несколько
прилагательных и существительное для имени свойства;
2) используйте стиль Паскаль для регистра букв.
Пример:
public class Control
{
public Color Color
{
get {/* Insert code here. */}
set {/* Insert code here. */}
108

}
}
Параметры:
1) из имени и типа параметра должны быть понятны его
назначение и смысл;
2) используйте стиль Кэмел для регистра букв в имени параметра;
3) старайтесь избегать указания типа в имени параметра.
16.3. Стиль кода
Оформление:
1) для отступов используйте табуляцию, а не пробелы. В средах типа
Visual Studio лучше использовать режим табуляции. Его можно
настроить в диалоге Options -> Text Editor -> Ваш_любимый_язык
->Tabs: Indenting = Smart, Tabs = Keep Tabs. В общем, это
настройки по умолчанию для многих языков;
2) для форматирования текста (кроме отступа в начале строки)
используйте пробелы;
3) избегайте длинных строк более 78 символов, при
необходимости переносите инструкцию на другую строку;
4) при переносе части кода инструкций и описаний на другую
строку вторая и последующая строки должны быть отодвинуты
вправо на один отступ (табуляцию).
Пробелы в строке:
1) после запятой должен быть пробел. После точки с запятой, если
она не последняя в строке (напр. в инструкции for), должен
быть пробел. Перед запятой или точкой с запятой пробелы не
ставятся;
2) все операторы должны быть отодвинуты пробелом от операндов
с двух сторон.
109

Локальные переменные:
1) используйте стиль Кэмел для регистра букв в именах
переменных;
2) объявляйте переменные непосредственно перед их
использованием;
3) счетчики в циклах традиционно называют i, j, k, l, m, n.
Пример:
class Class1
{
private int _totalLineCount = 0;
void SomeFunction(int startValue)
{
int lineCount = startValue;
using (StreamReader sr =
File.OpenText(@"c:\MyFile.txt"))
{
while (sr.ReadLine() != null)
lineCount++;
}
_totalLineCount = lineCount;
}
}
Комментарии:
1) лучше не использовать многострочные (/*...*/) комментарии для
описания классов и методов, правильнее использовать для этих
целей XML documentation-комментарии. Многострочные
комментарии не могут быть вложенными, поэтому их
использование может создать проблему;
2) для описания сути участков кода, пояснений к алгоритмам и
другой важной информации необходимо использовать
несколько подряд идущих однострочных комментариев (//...).
Между группой комментариев и собственно кодом ставьте
пустую строку. Это покажет, что комментарий относится к
110
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
