|
Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет: Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.
Как активировать код? |
Основы языка C#. Часть 1
Статические члены класса
Применение слова static к членам класса ( или структуры ) устанавливает за этим членом способ адресации только по имени класса, а не по имени экземпляров этого класса. Это значит, что можно использовать данные или метод даже тогда, когда не существует ни одного объекта такого типа.
Статические члены-данные в памяти компьютера занимают только одну постоянную область памяти, которая выделяется для хранения их значений сразу после загрузки программы, в которой есть классы со статическими членами. Предполагается, что их можно обрабатывать и тогда, когда еще не создано ни одного экземпляра. Поэтому и методы, которые должны обрабатывать эти статические данные, также необходимо помечать как статические. Для экземплярных данных создаются свои все новые области памяти с помощью оператора new, и обычные методы, вызываемые по имени объекта, обрабатывают именно данные конкретного экземпляра.
Таким образом, обычные данные-члены и обычные методы вызываются по имени экземпляра, а статические данные и методы вызываются по имени класса.В связи с этим, статические методы не могут использовать обычные поля и обычные методы, ибо последние начинают существовать только после создания экземпляра. Но обычные методы могут использовать статические данные и статические методы, ибо последние начинают существовать сразу после загрузки программы.
Естественно, что статические методы могут иметь внутри себя локальные нестатические переменные (не путайте с полями класса). Для них память выделяется в процессе загрузки метода в стек при его вызове, а освобождается сразу после возвращения из метода.
В одном классе может одновременно объявляться любое количество членов уровня класса и членов уровня экземпляра. Но если в статическом методе попытаться использовать нестатические члены класса (обратится к обычному полю или методу), то компилятор выдаст ошибку.
Приведем пример программы генерации бросков в кости, использующей статические члены класса
using System;
class Bones // Игра в кости
{
// Объявление статического поля
private static Random rnd = new Random();
// Объявление и определение статических методов
private static int GetRandomNumber(short maxValue)
{
return rnd.Next(maxValue);
}
public static string Throw()// Бросок
{
string[] messages = new string[6] { "Единица",
"Двойка",
"Тройка",
"Четверка",
"Пятерка",
"Шестерка" };
return messages[GetRandomNumber(6)];
}
}
class Start
{
static void Main()
{
// Выводим броски
for (int i = 0; i < 10; i++)
Console.WriteLine("{0}) {1}", i + 1, Bones.Throw());
Console.ReadLine();
}
}
Листинг
7.9.
Генерация бросков нумерованного шестигранного куба на уровне класса
Метод Throw() объявлен статическим и использует вспомогательную функцию GetRandomNumber(), которая в свою очередь использует поле rnd. Поэтому все вспомогательные члены должны быть статическими. Попробуйте убрать слово static из объявления поля rnd или метода GetRandomNumber() - компилятор сразу выдаст ошибку.
Если бы метод Throw() не был объявлен как static, то нужно было бы создать экземпляр класса Bones и вызывать метод на объектном уровне. При этом поле rnd и вспомогательный метод GetRandomNumber() можно оставить статическими
using System;
class Bones // Игра в кости
{
// Объявление статического поля
private static Random rnd = new Random();
// Объявление и определение статических методов
private static int GetRandomNumber(short maxValue)
{
return rnd.Next(maxValue);
}
public string Throw()// Бросок
{
string[] messages = new string[6] { "Единица",
"Двойка",
"Тройка",
"Четверка",
"Пятерка",
"Шестерка" };
return messages[GetRandomNumber(6)];
}
}
class Start
{
static void Main()
{
// Создаем экземпляр класса (объект)
Bones cube = new Bones();
// Выводим броски
for (int i = 0; i < 10; i++)
Console.WriteLine("{0}) {1}", i + 1, cube.Throw());
Console.ReadLine();
}
}
Листинг
7.10.
Генерация бросков нумерованного шестигранного куба на уровне объекта
Обе приведенных программы генерируют одинаковый алгоритм. Только в первом случае данные размещаются в самом объекте-типе (там, где размещаются коды методов), а во втором - в объекте-экземпляре типа.
Когда мы моделируем какую-то задачу с помощью класса, то часть параметров этой модели будет общей для всех экземпляров этого класса и ее разумно поместить в отдельную область памяти, доступную всем экземплярам, а не использовать для каждого экземпляра новую память с одинаковым содержимым.
Пусть, например, мы моделируем задачу учета студентов одного факультета. Класс, содержащий данные об одном студенте, будет одновременно иметь индивидуальные для студента характеристики (ФИО, возраст, ...) и общие данные, характерные для студентов одного института и факультета (название, адрес института, учебный корпус). Общие данные удобно сделать статическими и определить их один раз при загрузке программы, после чего они будут доступны всем экземплярам класса студент.
Приведем пример
using System;
class Student // Модель одного студента
{
// Члены уровня класса
private static string institute = "КИЦМ"; // Институт
public static void ChangeInstitute(string ins)
{ institute = ins; }
private static string faculty = "Горный"; // Факультет
public static void ChangeFaculty(string fac)
{ faculty = fac; }
// Члены объектного уровня
private string surName; // Фамилия
private int age, rate; // Возраст, курс
// Конструктор
public Student(string surName, int age, int rate)
{
this.surName = surName;
this.age = age;
this.rate = rate;
}
// Метод печати всей информации о студенте
public void Show()
{
Console.WriteLine("Студент {0}: ", surName);
Console.Write("Институт " + institute
+ ", факультет " + faculty);
Console.WriteLine(", возраст " + age
+ ", курс " + rate);
Console.WriteLine(); // Создание пустой строки
}
}
class Start
{
static void Main()
{
// Настройка консоли
Console.Title = "Статические и объектные члены";
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
// Создаем массив ссылок
Student[] students = new Student[3];
// Создаем несколько студентов
students[0] = new Student("Иванов", 18, 1);
students[1] = new Student("Петров", 19, 2);
students[2] = new Student("Сидоров", 20, 3);
// Выводим студентов до реорганизации
Console.WriteLine("Студенты до реорганизации:");
for (int i = 0; i < students.Length; i++)
students[i].Show();
// Меняем общее для всех студентов
// название института и факультета
Student.ChangeInstitute("СФУ");
Student.ChangeFaculty("ФФО");
// Выводим студентов после реорганизации
Console.WriteLine(Environment.NewLine + "Студенты
после реорганизации:");
for (int i = 0; i < students.Length; i++)
students[i].Show();
Console.ReadLine();
}
}
Листинг
7.11.
Совместное использование общих и индивидуальных данных
Мы видим, что каждый экземпляр класса использует как общие для всех студентов данные, так и индивидуальные данные для каждого студента. Общие данные хранятся в одной отдельной области памяти, а индивидуальные - в каждом экземпляре студента.
