Сформулируем теперь точные правила, справедливые для присваивания и передачи аргументов в процедуру. Для того, чтобы было возможным неявное преобразование массива с элементами класса S в массив с элементами класса T, необходимо выполнение следующих условий:
• классы S и T должны быть ссылочного типа;
• размерности массивов должны совпадать;
• должно существовать неявное преобразование элементов класса S в элементы класса T.
Заметьте, если S — это родительский класс, а T — его потомок, то для массивов одной размерности остальные условия выполняются. Вернемся теперь к примеру с классами Int [], String[] и Object []. Класс int не относится к ссылочным классам, и потому преобразования класса Int[] в Object [] не существует. Класс string является ссылочным классом и потомком класса Object, а потому существует неявное преобразование между классами String [] и Object [].
Правило для явного преобразования можно сформулировать, например, так. Если существует неявное преобразование массива с элементами класса S в массив с элементами класса T, то существует явное преобразование массива с элементами класса T в массив с элементами класса S.
Для демонстрации преобразований между массивами написана еще одна процедура печати. Вот ее текст:
public static void PrintArObj (string name,object[] A)
{
Console.WriteLine(name);
foreach (object item in A)
Console.Write("\t {0}", item);
Console.WriteLine();
}//PrintArObj
Как видите, формальный аргумент этой процедуры принадлежит классу Object []. при ее вызове фактическими аргументами могут быть массивы, удовлетворяющие выше указанным условиям. Вот пример кода, в котором вызывается эта процедура. В этом же фрагменте показаны и присваивания массива одного класса другому, где выполняются явные и неявные преобразования массивов.
public void TestMas()
{
string[] winames = ("Т. Xoap", "H. Вирт", "Э. Дейкстра"};
Arrs.PrintArObj("winames", winames);
object[] cur = new object[5];
cur = winames;
Arrs.PrintArObj("cur", cur);
winames = (string[])cur;
Arrs.PrintArObj("winames", winames);
}//TestMas
Взгляните на результаты работы этой процедуры.
Рис. 12.6. Семантика присваивания и преобразования массивов
Приступая к описаниям массивов, я полагал, что 10 страниц одной лекции будет вполне достаточно. Оказалось, что массивы C# более интересны. Надеюсь, с этим согласятся и читатели.
… В исходнике 13 лекция пропущена…
14. Строки С#. Классы String и StringBuilder
Строки С#. Класс String. Изменяемые и неизменяемые строковые классы. Классы Net Framework, расширяющие строковый тип. Класс StringBuilder.
В предыдущей лекции мы говорили о символьном типе char и строках постоянной длины, задаваемых массивом символов. Основным типом при работе со строками является тип string, задающий строки переменной длины. Класс String в языке C# относится к ссылочным типам. Над строками — объектами этого класса — определен широкий набор операций, соответствующий современному представлению о том, как должен быть устроен строковый тип.
Объявление строк. Конструкторы класса string
Объекты класса String объявляются как все прочие объекты простых типов — с явной или отложенной инициализацией, с явным или неявным вызовом конструктора класса. Чаще всего, при объявлении строковой переменной конструктор явно не вызывается, а инициализация задается строковой константой. Но у класса Sring достаточно много конструкторов. Они позволяют сконструировать строку из:
• символа, повторенного заданное число раз;
• массива символов char[];
• части массива символов.
Некоторым конструкторам в качестве параметра инициализации можно передать строку, заданную типом char*. Но все это небезопасно, и подобные примеры приводиться и обсуждаться не будут. Приведу примеры объявления строк с вызовом разных конструкторов:
public void TestDeclStrings()