Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет: Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.
Как активировать код? |
Консольные приложения в С#
Типы данных в C#
В C# различают структурные типы ( reference-based ) и ссылочные ( value-based ). Переменная структурного типа представляет закрепленное за ней само значение оперативной памяти. Переменная ссылочного типа содержит лишь адрес области оперативной памяти с размещаемым в этой области значением. Все структурные переменные размещаются на стеке, а ссылочные - на управляемой куче ( managed heap ). К структурным типам относятся перечисления и структуры, а к ссылочным - классы, массивы, указатели, интерфейсы.
Когда выполняется присваивание одной структурной переменной другой, то создается побитовая копия данных, которые размещены в разных областях стековой памяти и существуют независимо друг от друга. При выполнении присваивания ссылочных переменных создается копия адреса, после чего обе переменные будут ссылаться на одну и ту же область памяти на управляемой куче. То есть создается как-бы псевдонимы одной и той же области памяти. Это означает, что изменения объекта по одной ссылочной переменной равноценно изменениям по псевдониму
- Создайте консольное приложение C# или модифицируйте уже созданное. Заполните файл с точкой входа следующим кодом
using System; namespace Test { struct FOO { public int x, y; } class ValRefClass { static void Main(string[] args) { // Создаем объект на стеке // При создании структуры с конструктором по умолчанию // ключевое слово new является необязательным, // а можно просто FOO f1; FOO f1 = new FOO(); f1.x = 100; f1.y = 100; // Создается объект на стеке без ключевого слова new // и осуществляется побитовое копирование в другую память FOO f2 = f1; // Вывод до изменения Console.WriteLine("Содержимое объектов f1 и f2 до изменения"); Console.WriteLine("Объект f1: x={0}; y={1}", f1.x, f1.y); Console.WriteLine("Объект f2: x={0}; y={1}", f2.x, f2.y); // Внесение изменений f1.x = 1; f1.y = 2; f2.x = 3; f2.y = 4; // Вывод после изменения Console.WriteLine("\nСодержимое объектов f1 и f2 после изменения"); Console.WriteLine("Объект f1: x={0}; y={1}", f1.x, f1.y); Console.WriteLine("Объект f2: x={0}; y={1}", f2.x, f2.y); while(true); } } }Листинг 20.10 . Код для переменных структурного типа
Результаты экрана
Содержимое объектов f1 и f2 до изменения Объект f1: x=100; y=100 Объект f2: x=100; y=100 Содержимое объектов f1 и f2 после изменения Объект f1: x=1; y=2 Объект f2: x=3; y=4
- Измените в исходном коде для типа FOO ключевое слово struct на class, тем самым сразу получим ссылочный тип. Запустите программу - получится результат
using System; namespace Test { class FOO { public int x, y; } class ValRefClass { static void Main(string[] args) { // Создаем объект на куче // Теперь слово new является обязательным, а также // обазательны круглые скобки конструктора по умолчанию FOO f1 = new FOO(); f1.x = 100; f1.y = 100; // Создается не объект, а ссылку, и после копирования // адреса получаем псевдоним на ту же область памяти FOO f2 = f1; // Вывод до изменения Console.WriteLine("Содержимое объектов f1 и f2 до изменения"); Console.WriteLine("Объект f1: x={0}; y={1}", f1.x, f1.y); Console.WriteLine("Объект f2: x={0}; y={1}", f2.x, f2.y); // Внесение изменений f1.x = 1; f1.y = 2; f2.x = 3; f2.y = 4; // Вывод после изменения Console.WriteLine("\nСодержимое объектов f1 и f2 после изменения"); Console.WriteLine("Объект f1: x={0}; y={1}", f1.x, f1.y); Console.WriteLine("Объект f2: x={0}; y={1}", f2.x, f2.y); while(true); } } }Листинг 20.11 . Код для переменных ссылочного типа
Результаты экрана
Содержимое объектов f1 и f2 до изменения Объект f1: x=100; y=100 Объект f2: x=100; y=100 Содержимое объектов f1 и f2 после изменения Объект f1: x=3; y=4 Объект f2: x=3; y=4
Здесь мы видим, что в обоих случаях мы изменяли один и тот же объект, который и сохранил последние значения. Теперь f1 и f2 - не более чем ссылки на один и тот же диапазон памяти в области управляемой кучи.
Для того, чтобы объекты, адресуемые переменными f1 и f2, занимали разные области памяти, нужно запросить память у операционной системы для каждого из них и сохранить возвращенные адреса в этих переменных.
Следующий код и полученный результат иллюстрируют сказанное
using System; namespace Test { class FOO { public int x, y; } class ValRefClass { static void Main(string[] args) { // Создаем первый объект на куче FOO f1 = new FOO(); f1.x = 100; f1.y = 100; // Создается второй объект на куче FOO f2 = new FOO(); f2.x = 100; f2.y = 100; // Вывод до изменения Console.WriteLine("Содержимое объектов f1 и f2 до изменения"); Console.WriteLine("Объект f1: x={0}; y={1}", f1.x, f1.y); Console.WriteLine("Объект f2: x={0}; y={1}", f2.x, f2.y); // Внесение изменений f1.x = 1; f1.y = 2; f2.x = 3; f2.y = 4; // Вывод после изменения Console.WriteLine("\nСодержимое объектов f1 и f2 после изменения"); Console.WriteLine("Объект f1: x={0}; y={1}", f1.x, f1.y); Console.WriteLine("Объект f2: x={0}; y={1}", f2.x, f2.y); while(true); } } }Листинг 20.12 . Код для переменных ссылочного типа
Результаты экрана
Содержимое объектов f1 и f2 до изменения Объект f1: x=100; y=100 Объект f2: x=100; y=100 Содержимое объектов f1 и f2 после изменения Объект f1: x=1; y=2 Объект f2: x=3; y=4
Общие сравнения структурных и ссылочных типов
Поставим некоторые предварительные вопросы и ответы на них в таблице
Несмотря на все различия, структурные и ссылочные типы могут иметь и поддерживать как встроенные (стандартные), так и определенные пользователем (программистом) методы, свойства, события в необходимом количестве. Но удобно за структурными типами закреплять только поддержку сложных данных.
Продемонстрируем сказанное простым примером.
- Внесите следующие изменения в файл Test.cs консольного приложения C# с именем Test
using System; namespace Test { //********************************************************** struct PERSON // Структурный тип { private string Name;// Прямая инициализация не допускается private int Age;// Прямая инициализация не допускается //**************************************** // Объявления перегружаемых конструкторов // Конструктор по умолчанию перегружать нельзя!!! //**************************************** public PERSON(string name, int age) { Name = name; Age = age; } //**************************************** public PERSON(int age, string name) { Age = age; Name = name; } //**************************************** // Сервисы //**************************************** public string GetName() { return Name; } //**************************************** public void SetName(string name) { Name = name; } //**************************************** public int GetAge() { return Age; } //**************************************** public void SetAge(int age) { Age = age; } } //********************************************************** class Person // Ссылочный тип { private string Name = "Иванов";// Прямая инициализация допустима private int Age = 20;// Прямая инициализация допустима //**************************************** // Перегружаемые конструкторы // Конструктор по умолчанию перегружать можно //**************************************** public Person(){} //**************************************** public Person(string name, int age) { Name = name; Age = age; } //**************************************** public Person(int age, string name) { Age = age; Name = name; } //**************************************** public Person(string name) { Name = name; } //**************************************** public Person(int age) { Age = age; } //**************************************** // Сервисы //**************************************** public string GetName() { return Name; } //**************************************** public void SetName(string name) { Name = name; } //**************************************** public int GetAge() { return Age; } //**************************************** public void SetAge(int age) { Age = age; } } class ValRefClass { static void Main() { // Создаем объект на стеке PERSON petrov = new PERSON("Денис Петров", 23);// Общий конструктор PERSON empty = new PERSON();// Другой объект с конструктором по умолчанию // Круглые скобки обязательны // Создаем объект на куче Person sergey = new Person(21, " Сережа Жук!"); Person ivanov = new Person(); // Создание с конструктором по умолчанию // Вывод из стека Console.WriteLine("Содержимое объектов на стеке"); Console.WriteLine("Объект petrov: Имя={0}; возраст={1}",petrov.GetName(), petrov.GetAge()); Console.WriteLine("Объект empty: Имя={0}; возраст={1}",empty.GetName(), empty.GetAge()); Console.WriteLine("\n"); // Вывод из кучи Console.WriteLine("Содержимое объектов на куче"); Console.WriteLine("Объект sergey: Имя={0}; возраст={1}",sergey.GetName(), sergey.GetAge()); Console.WriteLine("Объект ivanov: Имя={0}; возраст={1}",ivanov.GetName(), ivanov.GetAge()); while(true); } } }Листинг 20.13 . Использование структурных и ссылочных типов в файле Test.cs
Результаты экрана
Содержимое объектов на стеке Объект petrov: Имя=Денис Петров; возраст=23 Объект empty: Имя=; возраст=0 Содержимое объектов на куче Объект sergey: Имя=Сережа Жук!; возраст=21 Объект ivanov: Имя=Иванов; возраст=20