Опубликован: 25.03.2010 | Доступ: свободный | Студентов: 1447 / 157 | Оценка: 4.31 / 4.00 | Длительность: 25:42:00
Лекция 20:

Консольные приложения в С#

< Лекция 19 || Лекция 20: 1234567891011

Базовый тип System.Object

Все типы в C#, как структурные, так и ссылочные, являются производными от одного общего предка - класса System.Object. Это подразумевается по умолчанию и нет необходимости явно указывать этот базовый класс при объявлении производного типа. Хотя ничего не мешает указать его явно. Ниже приведены варианты фрагмента кода, в которых объявления соответствующих типов идентичны

class Hello // Предок System.Object подразумевается по умолчанию
{
....................
}  
  
struct HELLO // Предок System.Object подразумевается по умолчанию
{
....................
}
Листинг 20.14 . Объявления типов без явного указания предка System.Object
class Hello : System.Object
{
....................
}  
  
struct HELLO : System.Object
{
....................
}
Листинг 20.15 . Объявления типов c явным указанием предка System.Object
using System;
  
namespace Test
{
class Hello : Object // Укороченно, т.к. пространство имен определено
  {
  ....................
  }  
  
struct HELLO : object // С маленькой буквы, потому что предусмотрен синоним
  {
  ....................
  }
}
Листинг 20.16 . Объявления типов c явным укороченным указанием предка System.Object

Ниже приведен код объявления библиотечного класса System.Object

namespace System
{
public class Object
{
  public Object();
  public virtual Boolean Equals(Object obj);
  public virtual Int32 GetHashCode();
  public Type GetType();
  public virtual String ToString();
  protected virtual void Finalize();
  protected Object MemberwiseClone();
}
}
Листинг 20.17 . Объявление библиотечного класса System.Object

Предназначение каждого метода приведено в таблице

Таблица 20.4 . Главные методы базового библиотечного класса System.Object
Метод Описание
Equals() Возвращает true, если сравниваемые сущности занимают одну и ту же область памяти. По умолчанию настроен для сравнивания объектов ссылочных типов. Для применения к объектам структурных типов этот метод и сопутствующий ему метод GetHashCode() нужно перегрузить своими методами.
GetHashCode() Возвращает целочисленное значение ID, идентифицирующее конкретный экземпляр объекта данного типа. Генерирует уникальный хэш.
GetType() Метод возвращает объект Type(), полностью описывающий тот объект, из которого этот метод был вызван. Это метод идентификации времени выполнения ( Runtime Type Identification - RTTI ) , который предусмотрен во всех объектах.
ToString() Возвращает символьное представление объекта в формате "путь_пространства_имен.имя_класса". Такой формат называется fully qualified name - полностью определенное имя. Если тип определен вне какого-либо пространства имен, возвращается только имя класса без именного пути. Этот метод может быть перегружен для предоставления информации о внутреннем состоянии объекта в формате имя-значение.
Finalize() Основное назначение этого метода - освободить все ресурсы, занятые объектом данного класса, перед его удалением для корректной работы сборщика мусора gc - Garbare Collector.
MemberwiseClone() Этот метод предназначен для создания еще одной ссылки на область, занимаемую объектом данного типа в оперативной памяти. Этот метод не может быть перегружен. Если требуется реализовать поддержку создания полной копии объекта в оперативной памяти, то необходимо реализовать поддержку интерфейса ICloneable

В следующем примере продемонстрированы возможности некотороых из перечисленных методов

using System;
  
namespace Test
{
//*******************************************************  
class ObjTest
{
}
  
//*******************************************************  
class App
{
  static void Main()
  {
  // Создаем объект на куче
  ObjTest obj1 = new ObjTest();
  
  // Выводим информацию, возвращенную методами 
  // базового класса System.Object
  Console.WriteLine("ToString(): {0}", 
    obj1.ToString());
  Console.WriteLine("GetHashCode(): {0}", 
    obj1.GetHashCode());
  Console.WriteLine("GetType(): {0}", 
    obj1.GetType().ToString());
  
  // Создаем еще две ссылки на объект obj1
  ObjTest obj2 = obj1;
  object obj3 = obj2;
  // Проверяем, действительно ли все три ссылки
  // указывают на одну и ту же область оперативной памяти
  if(obj1.Equals(obj2) && obj2.Equals(obj3))
    Console.WriteLine("Адресация памяти совпадает");
  
  while(true);
  }
  }
}
Листинг 20.18 . Демонстрация возможностей методов класса System.Object

Результаты экрана

ToString(): Test.ObjTest 
GetHashCode(): 2 
GetType(): Test.ObjTest 
Адресация памяти совпадает

Перегрузка стандартных методов класса System.Object

Перегружать в производном классе можно только методы, объявленные в базовом классе как виртуальные с префиксом virtual. Перегружаемый метод должен маркироваться ключевым словом override.

Методы, которые наследуются типами от базового класса System.Object, иногда могут не устраивать пользователя (программиста) при разработке своих типов. Поэтому может возникнуть необходимость перегружать некоторые из них. Покажем это на примерах.

Перегрузка (замещение) виртуального метода ToString()

Разработаем класс Person, в котором перегрузим метод ToString() так, чтобы он выдавал не имя класса, а внутреннее состояние объекта, из которого он вызывается.

Перегрузим, также, метод Equals() базового класса. Вспомним, что он возвращает значение true в случае, если сравниваемые ссылки указывают на один и тот же объект оперативной памяти. Пусть этот метод возвращает true, если у сравниваемых объектов одинакового типа совпадает внутреннее состояние, т.е. значения всех внутренних переменных совпадают.

Если мы перегружаем метод Equals(), то обязательно нужно перегрузить и сопутствующий ему метод GetHashCode(). Если етого не сделать, то компилятор выдаст предупреждение. Метод GetHashCode() возвражает числовое значение уникального идентификатора ID объекта в памяти. Чаще всего это значение используется в коллекциях, работающих с хэшами объектов. Нам достаточно применить эту функцию к любой переменной типа, производного от базового класса System.Object. Но любые встроенные в C# типы происходят от этого базового класса.

using System;
  
namespace Test
{
//**********************************************************************
// Класс, хранящий информацию о человеке
//**********************************************************************
class Person
{
//******************************************
// Закрытые (private) данные о человеке
//******************************************
string Name;// ФИО
string Inn; // Номер налогоплательщика
int Age;    // Возраст
  
//******************************************
// Конструкторы
//******************************************
public Person(){} // Пустой конструктор по умолчанию
  
//******************************************
public Person(string name, string inn, int age)
{
  Name = name;
  Inn = inn;
  Age = age;
}
  
//******************************************
// Сервисы
//******************************************
public void Set(string name, string inn, int age)
{
  Name = name;
  Inn = inn;
  Age = age;
}

//******************************************
public string GetName()
{
  return Name;
}
  
//******************************************
public string GetInn()
{
  return Inn;
}
  
//******************************************
public int GetAge()
{
  return Age;
}
  
//******************************************
// Перегрузка библиотечного метода ToString(),
// унаследованного от класса System.Object
//******************************************
public override string ToString()
{
  System.Text.StringBuilder sb = new System.Text.StringBuilder();
  sb.Append("Ф.И.О. = " + this.Name);
  sb.Append("\nИНН = " + this.Inn);
  sb.Append("\nВозраст = " + this.Age);

  return sb.ToString ();// Генерируется автоматически
}
  
//******************************************
// Перегрузка библиотечного метода Equals(),
// унаследованного от класса System.Object
//******************************************
public override bool Equals(object obj)
{
  Person tmp = (Person) obj; // Создаем еще одну ссылку
  // Проверяем совпадения значений переменных
  // текущего объекта this и переданного объекта obj
  if(tmp.Name == this.Name &&
    tmp.Inn == this.Inn &&
    tmp.Age == this.Age)
    return true;
  else
    return false;
}
  
//******************************************
// Перегрузка библиотечного метода GetHashCode(),
// связанного с методом Equals()
//******************************************
public override int GetHashCode()
{
  // Применяем к переменной Inn производного типа string
  return Inn.GetHashCode();
}
}
  
//**********************************************************************
// Клиент Main()
// Точка входа в приложение
//**********************************************************************
class App
{
static void Main()
{
// Создаем два объекта с одинаковыми состояниями
Person person1 = new Person("Серега Жук", 
  "2222-33-5555", 21);
Person person2 = new Person("Серега Жук", 
  "2222-33-5555", 21);

Console.WriteLine("Прервая проверка для 
  одинаковых объектов");
// Используем замещенный для сравнения внутренного сотояния метод Equals()
if(person1.Equals(person2) && person1.GetHashCode() == 
  person2.GetHashCode())
  Console.WriteLine("Состояние объектов person1 и 
    person2 совпадает");
else
  Console.WriteLine("Состояние объектов person1 и 
    person2 несовпадает");
        
// Меняем состояние одного из объектов
person2.Set("Андрей Косенок", 
  "1111-22-4444", 22);
Console.WriteLine("\nПовторная проверка для 
  различающихся объектов");
// Используем замещенный для сравнения внутренного 
  сотояния метод Equals()
if(person1.Equals(person2) && person1.GetHashCode() == 
  person2.GetHashCode())
  Console.WriteLine("Состояние объектов person1 и 
    person2 совпадает");
else
  Console.WriteLine("Состояние объектов person1 и 
    person2 несовпадает");
      
// Теперь используем замещенный (перегруженный) метод ToString()
Console.WriteLine("\nСодержимое объекта person1");
Console.WriteLine(person1.ToString());
Console.WriteLine("\nСодержимое объекта person2");
// Метод WriteLine() сам автоматически вызывает метод ToString()
Console.WriteLine(person2);
      
while(true);
}
}
}
Листинг 20.19 . Демонстрация перегруженных методов класса System.Object

Результаты экрана

Прервая проверка для одинаковых объектов
Состояние объектов person1 и person2 совпадает
  
Повторная проверка для различающихся объектов 
Состояние объектов person1 и person2 несовпадает
  
Содержимое объекта person1
Ф.И.О. = Серега Жук
ИНН = 2222-33-5555
Возраст = 21
  
Содержимое объекта person2
Ф.И.О. = Андрей Косенок
ИНН = 1111-22-4444
Возраст = 22
< Лекция 19 || Лекция 20: 1234567891011
Максим Филатов
Максим Филатов

Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет:

Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.

 

Как активировать код?