|
Прошел курс. Получил код 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