Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Другие элементы меню 8 страница




3. Даны описания процедур и переменных:
public static void L1_V1_Q31(int[] A, int S)
{
S=0;
for(int i =0; i< A.Length; i++) S+=A[i];
}

public static void L1_V1_Q32(ref int[] A, ref int S)
{
S=0;
for(int i =0; i< A.Length; i++) S+=A[i];
}

public static int L1_V1_Q34(object[] A)
{
int S=0;
foreach(int i in A) S+=(int)i;
return(S);
}

int sum =0;

int[] mas = {7, 6, 8};

object[] mas2 = {3, 9, 9};

Отметьте вызовы процедур, в которых переменная sum получит значение 21.

q Questions.L1_V1_Q31(mas, sum);

q Questions.L1_V1_Q32(ref mas, ref sum);

q sum = Questions.L1_V1_Q34(mas);

q sum = Questions.L1_V1_Q34(mas2);

Лекция 12. Класс Array и новые возможности массивов

Семейство классов-массивов. Родительский класс Array и наследуемые им интерфейсы. Новые возможности массивов в C#. Как корректно работать с массивами объектов?

Ключевые слова: класс System.Array; интерфейсы: ICloneable, IList, ICollection, IENumerable; коллекция; отношение наследования; статические методы: Copy, IndexOf, LastIndexOf, Reverse, Sort, BinarySearch; сортировка и поиск; преобразования; массивы объектов;

Класс Array

Нельзя понять многие детали работы с массивами в C#, если не знать устройство класса Array из библиотеки FCL, потомками которого являются все классы массивы. Рассмотрим следующие объявления:

//Класс Array

int[] ar1 = new int[5];

double[] ar2 ={5.5, 6.6, 7.7};

int[,] ar3 = new Int32[3,4];

Зададимся естественным вопросом, к какому или к каким классам принадлежат объекты ar1, ar2 и ar3? Ответ прост, все они принадлежат разным классам. Переменная ar1 принадлежит классу int[] – одномерному массиву значений типа int, ar2 – double[] – одномерному массиву значений типа double, ar3 – двумерному массиву значений типа int. Следующий закономерный вопрос, а что общего есть у этих трех объектов? Прежде всего, все три класса этих объектов, как и другие классы, являются потомками класса object, а потому имеют общие методы, наследованные от класса object и доступные объектам этих классов.

У всех классов, являющихся массивами, общего гораздо больше, поскольку все они потомки класса System.Array. Класс System.Array наследует ряд интерфейсов: ICloneable, IList, ICollection, IEnumerable, а, следовательно, обязан реализовать все методы и свойства этих интерфейсов. Помимо наследования свойств и методов класса Object и вышеперечисленных интерфейсов класс Array имеет довольно большое число собственных методов и свойств. Взгляните, как выглядит отношение наследования на семействе классов, определяющих массивы:

Рис. 12.1. Отношение наследования на классах – массивах

Благодаря такому мощному родителю, над массивами определены самые разные операции – копирование, поиск, обращение, сортировка, получение различных характеристик. Массивы можно рассматривать как коллекции и устраивать циклы For Each для перебора всех элементов. Важно и то, что, когда у семейства классов есть общий родитель, то можно иметь общие процедуры обработки различных потомков этого родителя. Для общих процедур работы с массивами характерно, что один или несколько формальных аргументов имеют родительский тип Array. Естественно, внутри такой процедуры может понадобиться анализ, какой реальный тип массива передан в процедуру.

Рассмотрим пример подобной процедуры. Ранее я для печати элементов массива использовал различные процедуры PrintAr1, PrintAr2 и так далее, по одной для каждого класса массива. Теперь я приведу общую процедуру, формальный аргумент которой будет принадлежать родителю всех классов-массивов, что позволит передавать массив любого класса в качестве фактического аргумента.

public static void PrintAr(string name, Array A)

{

Console.WriteLine(name);

switch (A.Rank)

{

case 1:

for (int i = 0; i<A.GetLength(0);i++)

Console.Write("\t" + name + "[{0}]={1}",

i, A.GetValue(i));

Console.WriteLine();

break;

case 2:

for (int i = 0; i<A.GetLength(0);i++)

{

for (int j = 0; j<A.GetLength(1);j++)

Console.Write("\t" + name + "[{0},{1}]={2}",

i,j, A.GetValue(i,j));

Console.WriteLine();

}

break;

default: break;

}

}// PrintAr

Вот как выглядит создание массивов и вызов процедуры печати:

public void TestCommonPrint()

{

//Класс Array

int [] ar1 = new int [5];

double [] ar2 ={5.5, 6.6, 7.7};

int [,] ar3 = new Int32[3,4];

Arrs.CreateOneDimAr(ar1);Arrs.PrintAr("ar1", ar1);

Arrs.PrintAr("ar2", ar2);

Arrs.CreateTwoDimAr(ar3);Arrs.PrintAr("ar3", ar3);

}// TestCommonPrint

Вот результаты вывода массивов ar1, ar2, ar3:

Рис. 12.2. Печать массивов. Результаты работы процедуры PrintAr

Приведу некоторые комментарии:

Первое, на что следует обратить внимание, формальный аргумент процедуры принадлежит базовому классу Array, наследниками которого являются все массивы в CLR и, естественно, все массивы C#.

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

К элементам массива A, имеющего класс Array, нет возможности прямого доступа в обычной манере – A[<индексы>], но зато есть специальные методы GetValue(<индексы>) и SetValue(<индексы>).

Естественно, разбор случаев можно продолжить, придав процедуре большую функциональность.

Заметьте, если разбор случаев вообще не делать, а использовать PrintAr только для печати одномерных массивов, то она будет столь же проста, как и процедура PrintAr1, но сможет печатать любые одномерные массивы, независимо от типа их элементов.

Массивы как коллекции

В ряде задач массивы C# целесообразно рассматривать как коллекции, не используя систему индексов для поиска элементов. Это, например, задачи, требующие однократного или многократного прохода по всему массиву – нахождение суммы элементов, нахождение максимального элемента, печать элементов. В таких задачах вместо циклов типа For по каждому измерению достаточно рассмотреть единый цикл For Each по всей коллекции. Эта возможность обеспечивается тем, что класс Array наследует интерфейс IEnumerable. Обратите внимание, этот интерфейс обеспечивает только возможность чтения элементов коллекции (массива), не допуская их изменения. Применим эту стратегию, и построим еще одну версию процедуры печати. Эта версия будет самой короткой и самой универсальной, поскольку подходит для печати массива, независимо от его размерности и типа его элементов. Вот ее код:

public static void PrintCollection(string name,Array A)

{

Console.WriteLine(name);

foreach (object item in A)

Console.Write("\t {0}", item);

Console.WriteLine();

}// PrintCollection

Конечно, за все нужно платить. Платой за универсальность процедуры печати является то, что многомерный массив печатается как одномерный без разделения элементов на строки.

К сожалению ситуация с чтением и записью элементов массива не симметрична. Приведу вариант процедуры CreateCollection:

public static void CreateCollection(Array A)

{

int i=0;

foreach (object item in A)

//item = rnd.Next(1,10); //item read only

A.SetValue(rnd.Next(1,10), i++);

}// CreateCollection

Заметьте, эту процедуру сделать универсальной не удается, поскольку невозможно модифицировать элементы коллекции. Поэтому цикл For Each здесь ничего не дает и разумнее использовать обычный цикл. Данная процедура не универсальна и позволяет создавать элементы только для одномерных массивов.

Сортировка и поиск. Статические методы класса Array

Статические методы класса Array позволяют решать самые разнообразные задачи:

5. Copy – позволяет копировать весь массив или его часть в другой массив;

6. IndexOf, LastIndexOf – определяют индексы первого и последнего вхождения образца в массив, возвращая -1, если такового вхождения не обнаружено;

7. Reverse – выполняет обращение массива, переставляя элементы в обратном порядке;

8. Sort – осуществляет сортировку массива;

9. BinarySearch – определяет индекс первого вхождения образца в отсортированный массив, используя алгоритм двоичного поиска.

Все методы перегружены и имеют ряд модификаций. Большинство из этих методов применимо только к одномерным массивам. Приведу примеры различных операций, доступных при работе с массивами, благодаря наследованию от класса Array:

public void TestCollection()

{

//операции над массивами

int nc = 7;

int [] col1 = new int [nc], col2 = new int [nc];

double [] col3 = new double [nc];

int [,] col4 = new int [2,2];

Arrs.CreateCollection(col1); Arrs.PrintCollection("col1",col1);

Arrs.CreateCollection(col2); Arrs.PrintCollection("col2",col2);

Arrs.CreateCollection(col3); Arrs.PrintCollection("col3",col3);

Arrs.CreateTwoDimAr(col4); Arrs.PrintCollection("col4",col4);

//сортировка, поиск, копирование

// поиск элемента

int first = Array.IndexOf(col1, 2);

int last = Array.LastIndexOf(col1,2);

if (first == -1)

Console.WriteLine("Нет вхождений 2 в массив col1");

else if (first ==last)

Console.WriteLine("Одно вхождение 2 в массив col1");

Console.WriteLine("Несколько вхождений 2 в массив col1");

//first = Array.IndexOf(col4, 4); //только одномерный массив

Array.Reverse(col1);

Console.WriteLine("Обращение массива col1:");

Arrs.PrintCollection("col1",col1);

//Копирование

Array.Copy(col1, col3, col1.Length);

Console.WriteLine(" Массив col3 после копирования массива col1:");

Arrs.PrintCollection("col3",col3);

Array.Copy(col1,1,col2,1,2);

Console.WriteLine("копирование двух элементов col1 в col2:");

Arrs.PrintCollection("col1",col1);

Arrs.PrintCollection("col2",col2);

//быстрая сортировка Хоара

Array.Sort(col1);

Console.WriteLine("Отсортированный массив col1:");

Arrs.PrintCollection("col1",col1);

first = Array.BinarySearch(col1, 2);

Console.WriteLine("Индекс вхождения 2 в col1: {0}", first);

//Создание экземпляра (массива)

Array my2Dar = Array.CreateInstance(typeof (double), 2,3);

Arrs.PrintCollection("my2Dar",my2Dar);

//клонирование

my2Dar = (Array)col4.Clone();

Console.WriteLine("Массив my2Dar после клонирования col4:");

Arrs.PrintCollection("my2Dar",my2Dar);

// копирование CopyTo

col1.CopyTo(col2,0);

Console.WriteLine("Массив col2 после копирования col1:");

Arrs.PrintCollection("col2",col2);

}

В этой процедуре продемонстрированы вызовы различных статических методов класса Array. Для метода Copy показан вызов двух реализаций этого метода, когда копируется весь массив и часть массива. Закомментированный оператор вызова метода IndexOf напоминает о невозможности использования методов поиска при работе с многомерными массивами. Приведу результаты вывода, порожденные этим кодом:

Рис. 12.3. Результаты применения статических методов класса Array

Сводка свойств и методов класса Array

Многие возможности, которыми можно пользоваться при работе с массивами, уже обсуждены. В завершение этой темы приведем сводку всех свойств и методов класса Array.

Таблица 12-1. Свойства класса Array

Свойство Родитель Описание
IsFixedSize Интерфейс IList True, если массив статический
IsReadOnly Интерфейс IList Для всех массивов имеет значение false
IsSynchronized Интерфейс ICollection True или False в зависимости от того установлена ли синхронизация доступа для массива
SyncRoot Интерфейс ICollection Собственный метод синхронизации доступа к массиву. При работе с массивом его можно закрыть на время обработки, что запрещает его модификацию каким либо потоком: Array myCol = new int[]; lock(myCol.SyncRoot) { foreach (Object item in myCol) { // безопасная обработка массива }
Length   Число элементов массива
Rank   Размерность массива

 

Таблица 12-2. Статические методы класса Array

Метод Описание
BinarySearch Двоичный поиск. Описание и примеры даны в тексте.
Clear Выполняет начальную инициализацию элементов. В зависимости от типа элементов устанавливает значение 0 для арифметического типа, false – для логического типа, Null для ссылок, “” – для строк.
Copy Копирование части или всего массива в другой массив. Описание и примеры даны в тексте
CreateInstance Класс Array в отличие от многих классов может создавать свои экземпляры не только с помощью конструктора new, но и при вызове метода CreateInstance: Array my2Dar = Array.CreateInstance(typeof(double), 2,2);
IndexOf Индекс первого вхождения образца в массив. Описание и примеры даны в тексте.
LastIndexOf Индекс последнего вхождения образца в массив. Описание и примеры даны в тексте.
Reverse Обращение одномерного массива. Описание и примеры даны в тексте.
Sort Сортировка массива. Описание и примеры даны в тексте.

Таблица 12-3. Динамические методы класса Array

Метод Родитель Описание
Equals Класс Object Описание и примеры даны в предыдущих главах.
GetHashCode Класс Object Описание и примеры даны в предыдущих главах.
GetType Класс Object Описание и примеры даны в предыдущих главах.
ToString Класс Object Описание и примеры даны в предыдущих главах.
Clone Интерфейс ICloneable Позволяет создать плоскую или глубокую копию массива. В первом случае создаются только элементы первого уровня, а ссылки указывают на те же самые объекты. Во втором случае копируются объекты на всех уровнях. Для массивов создается только плоская копия.
CopyTo Интерфейс ICollection Копируются все элементы одномерного массива в другой одномерный массив, начиная с заданного индекса: col1.CopyTo(col2,0);
GetEnumerator Интерфейс IEnumerable Стоит за спиной цикла ForEach
GetLength   Возвращает число элементов массива по указанному измерению. Описание и примеры даны в тексте главы.
GetLowerBound, GetUpperBound   Возвращает нижнюю и верхнюю границу по указанному измерению. Для массивов нижняя граница всегда равна нулю.
GetValue, SetValue   Возвращает или устанавливает значение элемента массива с указанными индексами.
Initialize   Может быть применен только к массивам значимого типа. Инициализирует элементы, вызывая соответствующий конструктор. Как правило, не используется в обычных программах.

Класс Object и массивы

Давайте обсудим допустимость преобразований между классами-массивами и классом Object. Понятно, что существует неявное преобразование объекта любого класса в объект класса Object. Так что переменной типа Object всегда можно присвоить переменную типа массив. В другую сторону такое преобразование также существует, но оно должно быть явным. Как всегда, при проведении явных преобразований не гарантируется успешность их выполнения.

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

Приведу в качестве примера многострадальную процедуру печати объектов, многократные варианты которой уже были рассмотрены. На этот раз, формальный аргумент процедуры будет иметь тип Object – прародителя всех классов. Рассмотрим, как можно выяснить, что в процедуру передается массив, как определить тип этого массива и работать с ним уже как с массивом, а не как с переменной класса Object. Вот текст этой процедуры, названной PrintObject:

public static void PrintObj(object A)

{

Console.WriteLine("A.GetType()={0})", A.GetType());

if (A.GetType()==typeof(System.Int32[]))

{

int[] temp;

temp = (int[])A;

for(int i = 0; i<temp.GetLength(0);i++)

Console.Write("\t temp[{0}]={1}", i,temp[i]);

Console.WriteLine();

}

else

Console.WriteLine("Аргумент не является массивом целых");

}// PrintObject

Несколько замечаний к реализации:

Метод GetType, примененный к аргументу, возвращает не тип Object, а реальный тип фактического аргумента. Поэтому можно проанализировать, какому классу принадлежит объект, переданный в процедуру.

На каждой ветви разбора можно создать временный объект нужного типа и скопировать в него переданный аргумент. В данном примере рассматривается только одна ветвь, в которой создается целочисленный одномерный массив temp.

Заметьте, при присваивании значения переменной temp выполняется явное преобразование из класса Object в класс int[].

Имея переменную temp, выполнение нужных действий над массивом не представляет никаких трудностей.

Приведу два примера вызова этой процедуры:

//работа с процедурой PrintObject

//Корректный и некорректный вызовы

Arrs.PrintObj(col1);

Arrs.PrintObj(col3);

Вот какой вывод порождается этим фрагментом кода:

Рис. 12.4. Результаты работы процедуры PrintObj

Массивы объектов

Во всех рассмотренных примерах этой главы нам встречались массивы, элементы которых имели только простые значимые типы. В реальных программах массивы объектов и других ссылочных типов встречаются не менее часто. Каков бы не был тип элементов, большой разницы при работе с массивами нет. Но один важный нюанс все же есть, и его стоит отметить. Он связан с инициализацией элементов по умолчанию. Уже говорилось о том, что компилятор не следит за инициализацией элементов массива и доверяет инициализации, выполненной конструктором массива по умолчанию. Но для массивов ссылочного типа инициализация по умолчанию присваивает ссылкам значение Null. Это означает, что создаются только ссылки, но не сами объекты. По этой причине, пока не будет проведена настоящая инициализация с созданием объектов и заданием ссылок на конкретные объекты, работать с массивом ссылочного типа будет невозможно.

Рассмотрим детали этой проблемы на примере. Определим достаточно простой и интуитивно понятный класс, названный Winners, свойства которого задают имя победителя и его премию, а методы позволяют установить размер премии для каждого победителя и распечатать его свойства. Приведу код, описывающий этот класс:

/// <summary>

/// Класс победителей с именем и премией

/// </summary>

public class Winners

{

//поля класса

string name;

int price;

//статическое или динамическое поле rnd?

//static Random rnd = new Random();

Random rnd = new Random();

// динамические методы

public void SetVals(string name)

{

this. name = name;

this. price = rnd.Next(5,10)* 1000;

}// SetVals

public void PrintWinner(Winners win)

{

Console.WriteLine("Имя победителя: {0}," +

" его премия - {1}", win.name, win.price);

}// PrintWinner

}// class Winners

Коротко прокомментирую этот текст.

10. Свойство name описывает имя победителя, а свойство price – величину его премии.

11. Свойство rnd необходимо при работе со случайными числами.

12. Метод SetVals выполняет инициализацию. Он присваивает полю name значение, переданное в качестве аргумента, полю price – случайное значение.

13. Метод PrintWinner – метод печати свойств класса. Без подобного метода не обходится ни один класс.

14. В классе появится еще один статический метод InitAr, но о нем скажу чуть позже.

Пусть теперь в одном из методов нашего тестирующего класса Testing предполагается работа с классом Winners, начинающаяся с описания победителей. Естественно, задается массив, элементы которого имеют тип Winners. Приведу начало тестирующего метода, в котором дано соответствующее объявление:

public void TestWinners()

{

//массивы объектов

int nwin = 3;

Winners[] wins = new Winners[nwin];

string [] winames = {"Т. Хоар", "Н. Вирт", "Э. Дейкстра"};

 

В результате создан массив wins, состоящий из объектов класса Winners. Что произойдет, если попытаться задать значения полей объектов, вызвав специально созданный для этих целей метод SetVals? Рассмотрим фрагмент кода, осуществляющий этот вызов:

//создание значений элементов массива

for(int i=0; i < wins.Length; i++)

wins[i].SetVals(winames[i]);

На этапе выполнения будет сгенерировано исключение – нулевая ссылка. Причина понятна, хотя массив wins и создан, но это массив ссылок, имеющих значение null. Сами объекты, на которые должны указывать ссылки, не создаются в момент объявления массива ссылочного типа. Их нужно явно создавать. Ситуация аналогично объявлению массива массивов. И там необходим явный вызов конструктора для создания каждого массива на внутреннем уровне.

Как же создавать эти объекты? Конечно, можно возложить эту обязанность на пользователя, объявившего массив wins. Пусть он и создаст экземпляры для каждого элемента массива. Правильнее все-таки иметь в классе соответствующий метод. Метод должен быть статическим для того, чтобы его можно было вызывать еще до того, как созданы экземпляры класса, поскольку метод предназначен для создания этих самых экземпляров. Так в нашем классе появился статический метод InitAr:

//статический метод

public static Winners[] InitAr(Winners[] Winar)

{

for (int i=0; i < Winar.Length; i++)

Winar[i] = new Winners();

return (Winar);

}//InitAr

Методу передается массив объектов, возможно, с нулевыми ссылками. Он возвращает тот же массив, но уже с явно определенными ссылками на реально созданные объекты. Теперь достаточно вызвать этот метод, после чего можно спокойно вызывать и метод SetVals. Вот как выглядит правильная последовательность вызовов методов класса Winners:

Winners.InitAr(wins);

//создание значений элементов массива

for (int i=0; i < wins.Length; i++)

wins[i].SetVals(winames[i]);

//печать значений элементов массива

for (int i=0; i < wins.Length; i++)

wins[i].PrintWinner(wins[i]);

}// TestWinners

Теперь все корректно, массивы создаются, элементы заполняются нужными значениями, их можно распечатать:

Рис. 12.5. Печать элементов массива wins

Обратите внимание, всем победителям назначена одна и та же премия. Хотя понятно, что дело в программной ошибке, но в ней можно видеть и знак свыше. Коль скоро для победителей выбраны такие имена, почитаемые всеми программистами, то негоже пытаться расставить их по ранжиру даже в примере.

Что же касается ошибки, то она связана с тем, что в данном случае свойство rnd следует сделать статическим, чтобы оно было одно на все экземпляры класса. В тексте описания варианта класса приведены оба варианта объявления свойства, один из которых закомментирован.

Массивы. Семантика присваивания

Преобразования между классами массивов и родительскими классами array и object уже рассматривались. А существуют ли другие преобразования между классами массивов? Что происходит при присваивании x=e; (передаче аргументов в процедуру), если x и e – это массивы разных классов. Возможно ли присваивание? Ответ на этот вопрос положительный, хотя накладываются довольно жесткие ограничения на то, когда такие преобразования допустимы. Известно, например, что между классами int и object существуют взаимные преобразования, в одну сторону явное, в другую неявное. А вот между классами int[] и object[] нет ни явных, ни неявных преобразований. С другой стороны такое преобразование существует между классами string[] и object[]. В чем же тут дело, и где логика? Запомните, главное ограничение на возможность таких преобразований состоит в том, что элементы массивов должны иметь ссылочный тип. А теперь притянем сюда логику. Крайне желательно обеспечить возможность проведения преобразований между массивами, элементы которых принадлежат одному семейству классов, связанных отношением наследования. Такая возможность и была реализована. Для массивов с элементами значимых типов такую возможность не захотели или не смогли реализовать.

Сформулируем теперь точные правила, справедливые для присваивания и передаче аргументов в процедуру. Для того чтобы было возможным неявное преобразование массива с элементами класса S в массив с элементами класса T, необходимо выполнение следующих условий:

· классы S и T должны быть ссылочного типа;

· размерности массивов должны совпадать;

· должно существовать неявное преобразование элементов класса S в элементы класса T.

Заметьте, если S – это родительский класс, а T – его потомок, то для массивов одной размерности остальные условия выполняются. Вернемся теперь к примеру с классами int[], string[] и object[]. Класс int не относится к ссылочным классам, и потому преобразования класса int[] в object[] не существует. Класс string является ссылочным классом и потомком класса object, а потому существует неявное преобразование между классами string[] и object[].

Правило для явного преобразования можно сформулировать, например, так. Если существует неявное преобразование массива с элементами класса S в массив с элементами класса T, то существует явное преобразование массива с элементами класса T в массив с элементами класса S.

Для демонстрации преобразований между массивами написана еще одна процедура печати. Вот ее текст:




Поделиться с друзьями:


Дата добавления: 2014-12-25; Просмотров: 556; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.121 сек.