Страница 169 из 502
Как упоминалось в главе 9, если перегружается оператор ==, то обычно приходится переопределять методы Equals(object) и GetHashCode(), поскольку чаще всего требуется, чтобы метод Equals(object) и оператор == функционировали одинаково. Когда же переопределяется метод Equals(object), то следует переопределить и метод GetHashCode(), чтобы оба метода оказались совместимыми.
Метод ToString() возвращает символьную строку, содержащую описание того объекта, для которого он вызывается. Кроме того, метод ToString() автоматически вызывается при выводе содержимого объекта с помощью метода WriteLine(). Этот метод переопределяется во многих классах, что позволяет приспосабливать описание к конкретным типам объектов, создаваемых в этих классах. Ниже приведен пример применения данного метода.
<b>// Продемонстрировать применение метода ToString()</b>
<b>using System;</b>
<b>class MyClass {</b>
<b> static int count = 0; </b>
<b> int id;</b>
<b> public MyClass() {</b>
<b> id = count; </b>
<b> count++;</b>
<b> }</b>
<b> public override string ToString() {</b>
<b> return "Объект #" + id + " типа MyClass";</b>
<b> }</b>
<b>}</b>
<b>class Test {</b>
<b> static void Main() {</b>
<b> MyClass ob1 = new MyClass();</b>
<b> MyClass ob2 = new MyClass();</b>
<b> MyClass ob3 = new MyClass();</b>
<b> Console.WriteLine(ob1);</b>
<b> Console.WriteLine(ob2);</b>
<b> Console.WriteLine(ob3);</b>
<b> }</b>
<b>}</b>
При выполнении этого кода получается следующий результат.
<b>Объект #0 типа MyClass</b>
<b>Объект #1 типа MyClass</b>
<b>Объект #2 типа MyClass</b>
Как пояснялось выше, все типы в С#, включая и простые типы значений, являются производными от класса object. Следовательно, ссылкой типа object можно воспользоваться для обращения к любому другому типу, в том числе и к типам значений. Когда ссылка на объект класса object используется для обращения к типу значения, то такой процесс называется упаковкой. Упаковка приводит к тому, что значение простого типа сохраняется в экземпляре объекта, т.е. "упаковывается" в объекте, который затем используется как и любой другой объект. Но в любом случае упаковка происходит автоматически. Для этого достаточно присвоить значение переменной ссылочного типа object, а об остальном позаботится компилятор С#.
Распаковка представляет собой процесс извлечения упакованного значения из объекта. Это делается с помощью явного приведения типа ссылки на объект класса object к соответствующему типу значения. Попытка распаковать объект в другой тип может привести к ошибке во время выполнения.
Ниже приведен простой пример, демонстрирующий упаковку и распаковку.
<b>// Простой пример упаковки и распаковки.</b>
<b>using System;</b>
<b>class BoxingDemo { </b>
<b> static void Main() {</b>
<b> int x;</b>
<b> object obj;</b>
<b> x = 10;</b>
<b> obj = x; // упаковать значение переменной х в объект</b>
<b> int у = (int)obj; // распаковать значение из объекта, доступного по </b>
<b> // ссылке obj, в переменную типа int </b>
<b> Console.WriteLine(у);</b>
<b> }</b>
<b>}</b>
В этом примере кода выводится значение 10. Обратите внимание на то, что значение переменной х упаковывается в объект простым его присваиванием переменной obj, ссылающейся на этот объект. А затем это значение извлекается из объекта, доступного по его ссылке obj, и далее приводится к типу int.
Ниже приведен еще один, более интересный пример упаковки. В данном случае значение типа int передается в качестве аргумента методу Sqr(), который, в свою очередь, принимает параметр типа object.
<b>// Пример упаковки при передаче значения методу.</b>
<b>using System;</b>
<b>class BoxingDemo {</b>
<b> static void Main() {</b>
<b> int x; </b>
<b> x = 10;</b>
<b> Console.WriteLine("Значение x равно: " + x);</b>
<b> // значение переменной x автоматически упаковывается </b>
<b> // когда оно передается методу</b><b> Sqr().</b>