Эта книга послужит прекрасным пособием как для специалистов, желающих изучить C# — новый язык фирмы Microsoft, так и для начинающих пользователей, не владеющих ни одним языков программирования. Книга написана простым и доступным языком. Ее автор, Герберт Шилдт, получил мировую известность за серию других изданий по программированию.
Содержание
Предисловие
Структура книги
Опыт программирования не обязателен
Необходимое программное обеспечение
Не забудьте: код доступен через Internet
Для дальнейшего изучения
Об авторе
Глава 1. Основы языка C#
Генеалогическое древо языка C#
Создание языка С - начало современной эры программирования
Появление ООП и создание языка C++
Internet и появление языка Java
История создания языка C#
Связь C# с .NET Framework
Что такое .NET Framework
Как работает не зависящая от языка среда исполнения
Управляемый и не управляемый коды
Общая языковая спецификация
Объектно-ориентированное программирование
Инкапсуляция
Полиморфизм
Наследование
Первая простая программа
Компилирование из командной строки
Использование Visual C++ IDE
Анализ первой программы
Обработка синтаксических ошибок
Небольшое изменение программы
Вторая простая программа
Другие типы данных
Проект 1-1. Преобразование значений температуры
Два управляющих оператора
Оператор if
Цикл for
Использование блоков кода
Символ точки с запятой и позиционирование
Использование отступов
Проект 1-2. Усовершенствование программы по преобразованию значения температуры
Ключевые слова в языке C#
Идентификаторы
Библиотека классов C#
Контрольные вопросы
Глава 2. Типы данных и операторы
Строгий контроль типов данных в C#
Обычные типы данных
Целочисленные типы
Типы данных с плавающей точкой
Тип decimal
Символы
Булев тип данных
Форматирование вывода
Проект 2-1. Разговор с Марсом
Литералы
Шестнадцатеричные литералы
Символьные escape-последовательности
Строковые литералы
Переменные и их инициализация
Инициализация переменной
Динамическая инициализация
Область видимости и время жизни переменных
Операторы
Арифметические операторы
Операторы сравнения и логические операторы
Проект 2-2. Вывод таблицы истинности логических операторов
Оператор присваивания
Составные операторы присваивания
Преобразование типа в операциях присваивания
Выполнение операции приведения типа между несовместимыми типами данных
Приоритетность операторов
Выражения
Преобразование типов в выражениях
Использование пробелов и круглых скобок
Проект 2-3. Вычисление суммы регулярных выплат по кредиту
Контрольные вопросы
Глава 3. Управляющие операторы
Ввод символов с клавиатуры
Оператор if
Вложенные операторы if
Цепочка операторов if-else-if
Оператор switch
Вложенный оператор switch
Проект 3-1. Построение простой справочной системы C#
Цикл for
Некоторые варианты цикла for
Недостающие части цикла for
Циклы, не имеющие тела
Объявление управляющих переменных цикла внутри цикла for
Цикл while
Цикл do-while
Проект 3-2. Совершенствование справочной системы C#
Использование оператора break для выхода из цикла
Использование оператора continue
Оператор goto
Проект 3-3. Завершение создания справочной системы C#
Вложенные циклы
Контрольные вопросы
Глава 4. Классы, объекты и методы
Основные понятия класса
Общий синтаксис класса
Определение класса
Как создаются объекты
Переменные ссылочного типа и оператор присваивания
Методы
Добавление метода к классу Vehicle
Возврат управления из метода
Возвращение методом значений
Использование параметров
Дальнейшее усовершенствование класса Vehicle
Проект 4-1. Создание справочного класса
Конструкторы
Конструкторы с параметрами
Добавление конструктора к классу Vehicle
Оператор new
Деструкторы и "сборка мусора"
Деструкторы
Проект 4-2. Демонстрация работы деструкторов
Ключевое слово this
Контрольные вопросы
Глава 5. Подробнее о типах данных и операторах
Массивы
Одномерные массивы
Проект 5-1. Сортировка массива
Многомерные массивы
Двухмерные массивы
Массивы, имеющие более двух размерностей
Инициализация многомерных массивов
Невыровненные массивы
Присваивание ссылок на массив
Использование свойства Length
Проект 5-2. Класс Queue
Цикл foreach
Строки
Создание объектов класса String
Операции со строками
Массивы строк
Неизменность строк
Побитовые операторы
Побитовые операторы AND, OR, XOR и NOT
Операторы сдвига
Составные побитовые операторы
Проект 5-3. Класс ShowBits
Оператор ?
Контрольные вопросы
Глава 6. Детальное рассмотрение методов и классов
Управление доступом к членам класса
Модификаторы в C#
Проект 6-1. Усовершенствованный класс Queue
Передача объектов методу
Как передаются аргументы
Использование параметров с модификаторами ref и out
Использование модификатора ref
Использование модификатора out
Использование переменного количества аргументов
Возвращение объектов
Перегрузка метода
Перегрузка конструкторов
Вызов перегруженного конструктора с использованием ключевого слова this
Проект 6-2. Перегрузка конструктора Queue
Метод Main()
Возвращение значений методом Main()
Передача аргументов методу Main()
Рекурсия
Ключевое слово static
Проект 6-3. Алгоритм Quicksort
Контрольные вопросы
Глава 7. Перегрузка оператора, индексаторы и свойства
Перегрузка операторов
Синтаксис метода оператора
Перегрузка бинарных операторов
Перегрузка унарных операторов
Дополнительные возможности класса ThreeD
Перегрузка операторов сравнения
Основные положения и ограничения при перегрузке операторов
Индексаторы
Многомерные индексаторы
Свойства
Ограничения в использовании свойств
Проект 7-1. Создание класса Set
Контрольные вопросы
Глава 8. Наследование
Основы наследования
Доступ к членам класса при использовании наследования
Использование модификатора protected
Конструкторы и наследование
Вызов конструкторов наследуемого класса
Скрытие переменных и наследование
Использование ключевого слова base для доступа к скрытой переменной
Проект 8.1. Расширение возможностей класса Vehicle
Создание многоуровневой иерархии классов
Когда вызываются конструкторы
Ссылки на объекты наследуемого и наследующего классов
Виртуальные методы и переопределение
Для чего нужны переопределенные методы
Применение виртуальных методов
Использование абстрактных классов
Использование ключевого слова sealed с целью предотвращения наследования
Класс object
Упаковка и распаковка
Контрольные вопросы
Глава 9. Интерфейсы, структуры и перечисления
Интерфейсы
Реализация интерфейсов
Использование интерфейсных ссылок
Проект 9.1. Создание интерфейса Queue
Свойства интерфейса
Интерфейсные индексаторы
Наследование интерфейсов
Явная реализация
Структуры
Перечисления
Инициализация перечисления
Указание базового типа перечисления
Контрольные вопросы
Глава 10. Обработка исключений
Класс System.Exception
Основы обработки исключений
Использование блоков try и catch
Простой пример исключения
Второй пример исключения
Если исключение не перехвачено
Изящная обработка ошибок с помощью исключений
Использование нескольких операторов catch
Перехват всех исключений
Вложенные блоки try
Генерирование исключений
Повторное генерирование исключения
Использование блока finally
Более близкое знакомство с исключениями
Часто используемые исключения
Наследование классов исключений
Перехват исключений производного класса
Проект 10-1. Добавление исключений в класс Queue
Использование ключевых слов checked и unchecked
Контрольные вопросы
Глава 11. Ввод/вывод
Потоки ввода/вывода C#
Байтовые потоки и потоки символов
Предопределенные потоки
Классы потоков
Класс Stream
Классы байтовых потоков
Классы потоков символов
Двоичные потоки
Консольный ввод/вывод
Чтение данных с консоли
Вывод данных на консоль
Класс FileStream и байт-ориентированный ввод/вывод в файлы
Открытие и закрытие файла
Чтение байтов с помощью класса FileStream
Запись в файл
Ввод/вывод в символьные файлы
Использование класса StreamWriter
Использование класса StreamReader
Перенаправление стандартных потоков
Проект 11-1. Утилита сравнения файлов
Чтение и запись двоичных данных
Поток BinaryWriter
Поток BinaryReader
Демонстрация двоичного ввода/вывода
Произвольный доступ к содержимому файла
Преобразование числовых строк в их внутренние представления
Проект 11.2. Создание справочной системы
Контрольные вопросы
Глава 12. Делегаты, события, пространства имен и дополнительные элементы языка C#
Делегаты
Многоадресность делегатов
Преимущества использования делегатов
События
Широковещательное событие
Пространства имен
Объявление пространства имен
Директива using
Вторая форма синтаксиса директивы using
Аддитивность пространств имен
Вложенные пространства имен
Пространство имен, используемое по умолчанию
Проект 12-1. Помещение класса Set в пространство имен
Операторы преобразования
Препроцессор
Директива препроцессора #define
Директивы препроцессора #if и #endif
Директивы препроцессора #else и #elif
Директива препроцессора #undef
Директива препроцессора #error
Директива препроцессора #warning
Директива препроцессора #line
Директивы препроцессора #region и #endregion
Атрибуты
Атрибут Conditional
Атрибут Obsolete
Небезопасный код
Краткая информация об указателях
Ключевое слово unsafe
Ключевое слово fixed
Идентификация типа во время работы программы
Проверка типа с помощью ключевого слова is
Ключевое слово as
Ключевое слово typeof
Другие ключевые слова
Модификатор доступа internal
Ключевое слово sizeof
Ключевое слово lock
Поле readonly
Ключевое слово stackalloc
Оператор using
Модификаторы const и volatile
Что делать дальше
Контрольные вопросы
Приложение. Ответы на контрольные вопросы
Глава 1: Основы языка C#
Глава 2: Типы данных и операторы
Глава 3: Управляющие операторы
Глава 4: Классы, объекты и методы
Глава 5: Типы данных и операторы
Глава 6: Детальное рассмотрение методов и классов
Глава 7: Перегрузка операторов, индексаторы и свойства
Глава 8: Наследование
Глава 9: Интерфейсы, структуры и перечисления
Глава 10: Обработка исключений
Глава 11: Ввод/вывод
Глава 12: Делегаты, события, пространства имен и дополнительные элементы языка C#
Алфавитный указатель
ОТРЫВОК
Глава 2.
int count = 10; // переменной count задается начальное значение 10
char ch = 'X' // переменной ch присваивается символ X
float f = 1.2F; // переменной f присваивается значение 1.2
При объявлении двух и более переменных одного типа можно разделить переменные в списке запятыми и присвоить одной или нескольким из них начальное значение. Например:
int a, b = 8, c = 19, d; // переменным b и c присвоено начальное значение
В этом случае инициализированы только переменные b и c.
Динамическая инициализация В предыдущих примерах переменным присваивались только конкретные числовые значения (то есть значения, которые не были получены в результате вычисления какого-либо выражения). Но в C# можно инициализировать переменные и динамически, используя любое действительное выражение. Например, ниже приведена короткая программа, которая вычисляет объем цилиндра по заданному радиусу основания и высоте:
// В программе демонстрируется использование
// динамической инициализации переменной.
using System;
class DynInit {
public static void Main() {
double radius = 4, height = 5;
// Динамически инициализируется переменная volume
double volume = 3.1416 * radius * radius * height;
Переменная volume инициализируется динамически во время выполнения программы.
Console.WriteLine("Объем цилиндра равен: " + volume);
}
}
В этой программе объявляются три локальные переменные -radius, height и volume. Первые две, radius и height, инициализированы конкретными значениями. Переменная volume инициализируется динамически - ей присваивается значение, соответствующее объему цилиндра. Ключевым моментом является то, что в выражении инициализации может быть использован любой элемент, который уже был до этого объявлен (то есть действительный на время инициализации данной переменной). Таким элементом может быть метод, другая переменная или литерал.
Область видимости и время жизни переменных
Все переменные, которые мы использовали до этого момента, объявлялись в начале метода Main(). Но в C# можно объявлять локальные переменные и внутри блока. Как уже говорилось в главе 1, блок начинается открывающейся фигурной скобкой и заканчивается закрывающей фигурной скобкой. Он определяет область видимости, которая зависит от того, имеет ли данный блок вложенные блоки. Каждый раз, создавая блок, вы создаете новую область видимости, определяющую время жизни объявляемых переменных.
Наиболее важными областями видимости в C# являются те, которые определяются классом и методом. На данном этапе мы рассмотрим только область видимости, определяемую методом.
Область видимости, определяемая методом, начинается с открывающей фигурной скобки. Однако если этот метод имеет параметры, они также включаются в область видимости метода. Общее правило состоит в том, что объявленная внутри области видимости переменная является невидимой (то есть недоступной) для кода, который определен за этой областью. Следовательно, при объявлении переменной в пределах ее области видимости вы локализуете эту переменную и защищаете ее от неразрешенного доступа и модификации. Можно сказать, что правила, касающиеся области видимости
, обеспечивают фундамент для инкапсуляции.
Область видимости может быть вложенной. Например, каждый раз, создавая блок кода, вы создаете новую вложенную область видимости, и при этом внешняя область становится видимой для вложенной области. Это означает, что объекты, объявленные во внешней области видимости, будут видимы для кода из внутренней области видимости, но объекты, объявленные во внутренней области видимости, не будут видимы для кода внешней области видимости.
Чтобы понять это правило, рассмотрим следующую программу:
// В программе демонстрируется зависимость возможности доступа к
// переменной от области видимости, в которой она была объявлена.
using System;
class ScopeDemo {
public static void Main() {
int x; // Переменная x известна всему коду
// в пределах метода Main().
x = 10;
if(x == 10) { //Создается новая область видимости.
int y = 20; // Эта переменная будет видна только в рамках // этого блока.
// В данном блоке видны обе переменные, x и y.
Console.WriteLine("Видны x и y: " + x + " " + y);
x = y * 2;
}
// y = 100; // Ошибка! Переменная y здесь не видна!
y - это переменная, объявленная во вложенной области видимости, поэтому здесь она не видна.
// Выполняется доступ к переменной x, которая была объявлена
// в этой области видимости.
Console.WriteLine("Значение переменной x равно: " + x);
}
}
Как указано в комментариях, объявленная в методе Main() переменная x доступна всему коду в пределах этого метода. Переменная y объявляется в рамках блока if. Поскольку блок определяет область видимости, переменная y является видимой только в пределах самого блока. Вот почему использование переменной y в строке y = 100; вне своего блока является ошибкой, о чем и говорится в комментарии. Если вы удалите начальный символ комментария, произойдет ошибка компилирования, так как переменная y невидима за пределами своего блока. В рамках блока if может использоваться пере
менная x, поскольку в блоке (вложенной области видимости) код имеет доступ к переменным, объявленным во внешней области видимости.
Внутри блока переменная может быть объявлена в любом месте, после чего она становится действительной. Следовательно, если вы определите переменную в начале метода, она будет доступна всему коду в рамках метода. И наоборот, если вы объявите переменную в конце блока, то не сможете использовать ее до момента объявления, поскольку код не будет иметь к ней доступа.
Обратите внимание на еще один важный момент: переменные создаются при их объявлении в какой-либо области видимости (при входе в данную область) и уничтожаются при выходе из этой области. Это означает, что переменная не будет сохранять свое значение при выходе из своей области видимости, то есть переменная, объявленная в пределах метода, не будет хранить свои значения между вызовами этого метода. Также переменная, объявленная в рамках блока, будет терять свое значение при выходе из блока. Следовательно, время жизни переменной ограничено ее областью видим
ости.
Если при объявлении переменной одновременно происходит ее инициализация, то переменная будет повторно инициализироваться каждый раз при входе в блок, в котором она объявлена. В качестве примера рассмотрим следующую программу:
// В программе демонстрируется использование правила,
// определяющего время жизни переменной.
using System;
class VarInitDemo {
public static void Main() {
int x;
for(x = 0; x < 3; x++) {
int y = -1; // Переменная y инициализируется каждый раз
// при входе в блок.
Console.WriteLine("Значение переменной y равно: " + y);
// Всегда выводится значение -1.
y = 100;
Console.WriteLine("Теперь значение переменной y равно: " + y);
}
}
}
Ниже показан результат выполнения этой программы:
Значение переменной y равно: -1
Теперь значение переменной y равно: 100
Значение переменной y равно: -1
Теперь значение переменной y равно: 100
Значение переменной y равно: -1
Теперь значение переменной y равно: 100
Как видите, переменная y инициализируется значением -1 каждый раз при входе во внутренний цикл for, затем ей присваивается значение 100, которое утрачивается при завершении цикла.
Заметим, что между языками C# и С есть отличие в работе с областями видимости.
Несмотря на то, что блоки могут быть вложенными, переменная, объявленная во внутренней области видимости, не может иметь такое же имя, как переменная, объявленная во внешней области видимости. Следующая программа, в которой делается попытка объявить две переменные с одинаковыми именами, не будет скомпилирована:
/*
В этой программе делается попытка объявить во внутренней области
видимости переменную с тем же именем, что и у переменной,
объявленной во внешней области видимости.
*** Эта программа не будет скомпилирована. ***
*/
C#: учебный курс. / Г. Шилдт - СПб: Питер, 200?. - 512 с.
|