Шаг 101.
Язык программирования C#. Начала
Работа с текстом. Метод ToString()

    На этом шаге мы рассмотрим назначение и особенности использования этого метода.

    При создании класса в нем можно описать метод ToString(). Этот метод особый. Специфика его в том, что метод автоматически вызывается каждый раз, когда нужно преобразовать объект класса к текстовому формату. Представим себе ситуацию, что имеется некоторый класс и на основе этого класса создан объект. И вот этот объект передается аргументом методу WriteLine(). Если в классе описан метод ToString(), то этот метод автоматически будет вызван и текст, который метод вернет результатом, будет передан аргументом методу WriteLine() вместо ссылки на объект. Аналогичная ситуация имеет место, если в некотором выражении к объекту прибавляется текст (или к тексту прибавляется объект). Если так, то из объекта вызывается метод ToString(), а результат (текст), который возвращается методом, подставляется в выражение вместо ссылки на объект.


Если называть вещи своими именами, то здесь мы имеем дело с наследованием класса и переопределением метода. Этим темам будут посвящены отдельные шаги. Пока что мы приведем лишь краткую справку, необходимую для понимания принципов реализации программного кода.

    Наследование позволяет создавать новые (называются производными) классы на основе уже существующих (они называются базовыми). "Призом" в таком подходе является то, что открытые члены исходного класса (на основе которого создается новый класс) наследуются в создаваемом классе: хотя они в новом классе явно не описаны, но они там есть. Существует особый класс Object (из пространства имен System), который находится в вершине иерархии наследования. Любые классы, в том числе и описываемые нами в программе, являются прямыми или косвенными наследниками класса Object. В классе Object есть метод ToString(), поэтому, даже если мы в нашем классе такой метод не описываем, он там есть. Метод вызывается при необходимости преобразовать ссылку на объект к текстовому формату. Другое дело, что если явно метод ToString() в классе не описать, то преобразование выполняется так: вместо ссылки на объект получаем название класса, на основе которого объект создан. Это "поведение" метода ToString() по умолчанию - как оно определено в классе Object. Мы его можем "переопределить". Описывая в нашем классе метод ToString(), мы как раз выполняем переопределение этого метода. Это проявление общего универсального механизма, который позволяет переопределять в производном классе методы, унаследованные из базового класса. При переопределении методов используется ключевое слово override.


    Таким образом, у нас имеется возможность задать способ преобразования ссылок на объекты пользовательского класса к текстовому формату. Для этого в данном классе следует описать метод ToString(). Формальные требования, предъявляемые к описанию метода ToString(), следующие.

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace pr101_1
{
    // Класс с переопределением метода ToString(): 
    class MyClass
    {
        // Целочисленное поле: 
        public int num;
        // Символьное поле: 
        public char symb;
        // Конструктор:
        public MyClass(int n, char s)
        {
            // Присваивание значений полям:
            num = n;
            symb = s;
            // Отображение сообщения о создании объекта.
            // Неявно вызывается метод ToString():
            Console.WriteLine("Создан новый объект\n" + this);
        }

        // Переопределение метода ToString(): 
        public override String ToString()
        {
            // Локальная текстовая переменная:
            String txt = "Числовое поле: " + num;
            txt += "\nСимвольное поле: " + symb;
            // Результат метода: 
            return txt;
        }
    }

    // Класс с главным методом программы: 
    class Program
    {
        // Главный метод:
        static void Main()
        {
            // Создание нового объекта:
            MyClass obj = new MyClass(100, 'A');
            // Новые значения полей объекта:
            obj.num = 200;
            obj.symb = 'B';
            Console.WriteLine("Новые значения полей объекта"); 
            // Отображение значений полей объекта.
            // Неявно вызывается метод ToString():
            Console.WriteLine(obj);
            // Разбивка текста с описанием объекта на подстроки.
            // Метод ToString() вызывается в явном зиде:
            String[] str = obj.ToString().Split('\n');
            Console.WriteLine("Явный вызов метода ToString()");
            // Отображение подстрок, содержащих значения
            // полей объекта:
            for (int k = 0; k < str.Length; k++)
            {
                Console.WriteLine("[* " + str[k] + " *]");
            }
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Эта программа дает такой результат.


Рис.1. Результат выполнения программы

    В программе описан класс MyClass. У этого класса есть два открытых поля: целочисленное num и символьное symb. В классе переопределяется метод ToString(). Описывается метод следующим образом. В теле метода объявляется локальная текстовая переменная txt. Начальное значение переменной формируется как объединение текста "Числовое поле: " и значения поля num. Затем к текущему значению переменной txt дописывается текст "\nСимвольное поле: " и значение поля symb. Таким образом, переменная txt содержит текст со значениями полей объекта (подразумевается объект, из которого будет вызываться метод ToString()). После того как значение переменной txt сформировано, командой

  return txt;
это значение возвращается результатом метода.


Текст, возвращаемый в качестве результата методом ToString(), содержит символ перехода к новой строке '\n'. Это обстоятельство впоследствии используется при разбиении текста на подстроки.

    В классе также описан конструктор с двумя аргументами, которые определяют значения полей создаваемого объекта. Еще конструктор содержит команду

  Console.WriteLine("Создан новый объект\n" + this);    . 
Этой командой в консольном окне отображается сообщение о создании нового объекта и значении полей этого объекта. Причем при выполнении команды вызывается метод ToString() (метод вызывается, хотя явной команды вызова этого метода нет). Дело в том, что аргументом методу WriteLine() передается выражение, представляющее собой сумму текстового литерала и ссылки this, обозначающей созданный объект. Таким образом, мы имеем дело с выражением, в котором к тексту прибавляется ссылка на объект. Это тот случай, когда вызывается метод ToString() и полученный в результате текст подставляется вместо ссылки this.

    В главном методе программы командой

  MyClass obj = new MyClass(100, 'A');
создается объект. При его создании (вследствие вызова конструктора) отображается сообщение со значениями полей созданного объекта. Затем полям объекта присваиваются новые значения. Командой
  Console.WriteLine(obj);
отображаются новые значения полей объекта obj. Здесь для преобразования объекта obj к текстовому формату вызывается метод ToString(). Но этот метод можно вызывать и в явном виде, как обычный метод. Пример такой ситуации дается инструкцией
  String[] str = obj.ToString().Split('\n');    . 
Здесь из объекта obj вызывается метод ToString(). Результатом является текстовая строка. Из объекта этой строки вызывается метод Split() с аргументом '\n'. В результате создается массив, состоящий из подстрок, на которые разбивается исходный текст (результат инструкции obj.ToString()). Индикатором для разбивки текста на подстроки является символ '\n'. Такой символ в тексте, возвращаемом методом ToString(), всего один, поэтому текст разбивается на две подстроки. Ссылка на массив с подстроками записывается в переменную str. С помощью оператора цикла значения массива str отображаются в консольном окне, заключенные в комбинацию из квадратных скобок и звездочек.

    На следующем шаге мы резюмируем все ранее сказанное по данной теме на предыдущих шагах.




Предыдущий шаг Содержание Следующий шаг