Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Методичка по С#

.pdf
Скачиваний:
276
Добавлен:
13.02.2015
Размер:
3.13 Mб
Скачать

41

Console.WriteLine(“=================================================”); for (i = 0; i < 10; i++) Console.WriteLine(“{0}: {1}”, i, iArr[i]);

}

}

}

В процессе сортировки массива ключей элемент со значением ключа 10 перемещается в конец массива. При этом нулевой элемент целевого массива со значением 0 перемещается на последнюю позицию.

Целевой массив и массив ключей вида при сортировке

int[] iArr = {0,1,2,3,4,5,6,7,8,9}; // Целевой массив. int[] keys = {9,8,7,6,5,4,3,2,1,0}; // Массив ключей.

обеспечивают размещение элементов целевого массива в обратном порядке. Следующее сочетание значений целевого массива и массива ключей обеспечивает

изменение расположения первых четырёх элементов целевого массива:

int[] iArr = {0,1,2,3,4,5,6,7,8,9}; // Целевой массив. int[] keys = {3,2,1,0}; // Массив ключей.

А такие наборы значений целевого и ключевого элементов массива при сортировке с использованием массива ключей обеспечивают изменение порядка целевых элементов массива с индексами 4, 5, 6, 7.

int[] iArr = {0,1,2,3,4,5,6,7,8,9}; int[] keys = {0,1,2,9,8,7,6,10,11,12};

Но самое главное и самое интересное в методе сортировки с использованием ключевого массива – это то, что в этом никаким образом не участвуют значения элементов целевого массива.

Надо отсортировать (изменить порядок расположения) составляющих массив массивов компонентов – надо всего лишь установить соответствие между элементами целевого массива и элементами массива ключей – и вызвать соответствующий вариант метода сортировки. Составляющие массива массивов будут восприняты как объекты-представители класса object и, не вдаваясь в

подробности

по

какому

принципу

упорядочивать

массивы?)

будут

переупорядочены в соответствии с новым

порядком расположения элементов

ключевого массива.

 

 

 

 

 

 

int[][] iArr = new int[3][]{ new int[]{0},

new int[]{0,1},

new int[]{0,1,2,3,4,5,6,7,8,9} };

int[] keys = {3,2,1};

Вариант метода, позволяющего организовать сортировку подмножества элементов целевого массива, начиная с элемента, заданного вторым параметром метода и включающим количество элементов, заданным вторым параметром.

public static void Sort(Array,int,int);

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

public static void Sort(Array,Array,int,int);

Сортировка на основе сравнения пар объектов-членов одномерного массива с использованием стандартного интерфейса сравнения

public static void Sort(Array,IComparer);

//Сортировка элементов с использованием стандартного Компарера.

//iArr – одномерный массив целочисленных значений.

//System.Collections.Comparer.DefaultInvariant стандартный Компарер.

try

41

42

{

System.Array.Sort(iArr,System.Collections.Comparer.DefaultInvariant);

}

catch (Exception ex)

{

Console.WriteLine(ex.ToString());

}

System.Collections.Comparer.DefaultInvariant - интерфейс определяет обобщённый метод сравнения значений (класса или типа), переопределение которого позволяет задать собственный специфический для данного класса метод сравнения элементов массива (interface implemented by each element of the Array).

using System;

using System.Collections;

namespace SortArrays

{

///<summary>

///Данные для массива элементов.

///Подлежат сортировке в составе массива методом Sort.

///Главная проблема заключается в том, что никто из тех, кто обеспечивает

///встроенную сортировку, ни в классе Array, ни в классе Items не знает,

///как воспринимать и каким образом сравнивать между собой

///объекты-представители класса Items. Объекты itObj0 b itObj1

///со значениями полей (7,5) и (5,7) - кто из них «больше»?

///</summary>

class Items

{

///<summary>

///Конечно, можно об определении аксиом для установления отношения

///порядка между элементами множества объектов-представителей класса

///Items и о реализации соответствующих методов сравнения

///можно было позаботиться при объявлении класса и просто не допускать

///к стандартной сортировке объекты классов, в которых не определено

///отношение порядка, однако в .NET используется другой подход.

///<summary>

public int val1; public int val2;

public Items (int key1, int key2)

{

val1 = key1; val2 = key2;

}

}

///<summary>

///Предполагается, что отношение порядка над элементами

///множества объектов-представителей соответствующего

///класса может быть введено в любой момент. Для этого

///достаточно иметь доступ к значениям соответствующих

///полей объектов.

///Для этого достаточно воспользоваться стандартными

///библиотечными средствами .NET и реализовать (доопределить)

///соответствующие интерфейсы (заготовки методов) сравнения.

///Ниже объявляются два варианта процедур сравнения,

///использование которых позволяет реализовать стандартные

///алгоритмы сортировки, применяемые в классе Array.

///...КОМПАРАТОРЫ...

///</summary>

class myComparer0: IComparer

{

int IComparer.Compare(object obj1, object obj2)

{

if (((Items)obj1).val1 == ((Items)obj2).val1) return 0;

42

43

if (((Items)obj1).val1 > ((Items)obj2).val1) return 1; if (((Items)obj1).val1 < ((Items)obj2).val1) return -1; else return 0;

}

}

class myComparer1: IComparer

{

int IComparer.Compare(object obj1, object obj2)

{

if (((Items)obj1).val2 == ((Items)obj2).val1) return 0; if (((Items)obj1).val2 > ((Items)obj2).val2) return 1; if (((Items)obj1).val2 < ((Items)obj2).val2) return -1; else return 0;

}

}

///<summary>

///После реализации соответствующего интерфейса объекты-компараторы,

///«профессиональные сравниватели», обеспечивают реализацию

///стандартных алгоритмов сортировки.

///</summary>

class Class1

{

[STAThread]

static void Main(string[] args)

{

//Объект-генератор «случайных» чисел.

//Стартует c использованием a time-dependent default seed value. Random rnd = new Random();

int i;

//Массив Items.

Items[] itArr = new Items[10];

//Создали две версии Компареров, способных сравнивать пары

//объектов-представителей класса Items.

myComparer0 c0 = new myComparer0(); myComparer1 c1 = new myComparer1();

Console.WriteLine(“=================================================”); // Проинициализировали массив объектов-представителей класса Items. for (i = 0; i < 10; i++)

{

itArr[i] = new Items(rnd.Next(0,10),rnd.Next(0,10));

}

for (i = 0; i < 10; i++)

{

Console.WriteLine(“{0}: {1},{2}”, i, itArr[i].val1, itArr[i].val2);

}

//Сортируются элементы массива типа Items.

//Условием успешной сортировки элементов массива является реализация

//интерфейса IComparer. Если Компарер не сумеет справиться с

//поставленной задачей - будет возбуждено исключение.

try

{

System.Array.Sort(itArr,c0);

}

catch (Exception ex)

{

Console.WriteLine(ex);

}

Console.WriteLine(“=================================================”); for (i = 0; i < 10; i++)

{

Console.WriteLine(“{0}: {1},{2}”, i, itArr[i].val1, itArr[i].val2);

}

43

44

Console.WriteLine(“=================================================”);

//Сортируются элементы массива типа Items.

//Условием успешной сортировки элементов массива является реализация

//интерфейса IComparer.

try

{

System.Array.Sort(itArr,c1);

}

catch (Exception ex)

{

Console.WriteLine(ex);

}

for (i = 0; i < 10; i++)

{

Console.WriteLine(“{0}: {1},{2}”, i, itArr[i].val1, itArr[i].val2);

}

}

}

}

Подробнее о массивах массивов (jagged array)

A jagged array также называют “массивом массивов”.

Прежде всего, элементы зубчатого массива на одном и том же уровне (элементы одной размерности) могут иметь разные размеры. На этих массивах функция GetLength() и свойство Rank показывают результаты, аналогичные простым одномерным массивам.

Рассмотрим примеры объявления, инициализации и доступа к элементам jagged arrays.

Вот объявление a single-dimensional (ОДНОМЕРНОГО!) массива, состоящего из трёх элементов, каждый из которых является одномерным массивом целых:

int[][] myJaggedArray = new int[3][];

Дальнейшее использование этого массива требует инициализации его элементов. Например, так:

myJaggedArray[0] = new int[5]; myJaggedArray[1] = new int[4]; myJaggedArray[2] = new int[2];

Каждый из элементов является single-dimensional массивом целых. Количество элементов каждого массива очевидно из соответствующих операторов определения.

Ниже показан пример использования заполняющей инициализации, при которой одновременно с определением (созданием) массивов производится присвоение элементам новорожденных массивов конкретных значений:

myJaggedArray[0] = new int[] {1,3,5,7,9}; myJaggedArray[1] = new int[] {0,2,4,6}; myJaggedArray[2] = new int[] {11,22};

Вышеупомянутый массив может быть объявлен и проинициализирован и таким образом:

int[][] myJaggedArray = new int [][]

{

new int[] {1,3,5,7,9}, new int[] {0,2,4,6}, new int[] {11,22}

};

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

44

45

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

int[][] myJaggedArray = { new int[] {1,3,5,7,9}, new int[] {0,2,4,6},

new int[] {11,22} };

Доступ к элементам ступенчатого массива обеспечивается посредством выражений индексации:

//Assign 33 to the second element of the first array: myJaggedArray[0][1] = 33;

//Assign 44 to the second element of the third array: myJaggedArray[2][1] = 44;

C# позволяет собирать разнообразные конструкции на основе jagged многомерных массивов. Ниже приводится пример объявления и инициализации одномерного jagged array, содержащего в качестве элементов двумерные массивы различных размеров:

int[][,] myJaggedArray = new int [3][,]

{

new int[,] { {1,3}, {5,7} },

new int[,] { {0,2}, {4,6}, {8,10} }, new int[,] { {11,22}, {99,88}, {0,9} }

};

Доступ к отдельным элементам jagged массива обеспечивается различными комбинациями выражений индексации. В приводимом ниже примере выводится значение элемента массива [1,0], расположенного по нулевому индексу myJaggedArray (это 5):

Console.Write(“{0}”, myJaggedArray[0][1,0]);

И ещё один пример, в котором строится массив myArray, элементами которого являются массивы. Каждый из составляющих имеет собственные размеры.

//cs_array_of_arrays.cs using System;

public class ArrayTest

{

public static void Main()

{

//Declare the array of two elements: int[][] myArray = new int[2][];

//Initialize the elements: myArray[0] = new int[5] {1,3,5,7,9}; myArray[1] = new int[4] {2,4,6,8};

//Display the array elements:

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

{

Console.Write(“Element({0}):”, i);

for (int j = 0 ; j < myArray[i].Length ; j++)

Console.Write(“{0}{1}”, myArray[i][j], j == (myArray[i].Length-1) ? “” : “ ”);

Console.WriteLine();

}

}

}

Результат:

Element(0): 1 3 5 7 9

Element(1): 2 4 6 8

45

46

Массивы как параметры

В качестве параметра методу всегда можно передать ссылку на ОДНОМЕРНЫЙ массив. Массив, первая спецификация размерности которого в объявлении имеет вид …[] …

Тип и количество составляющих данный массив компонентов для механизма передачи параметров значения не имеют. Важно, что в стеке будет выделено определённое (соответствующее значению первой размерности) количество проинициализированных ссылок на составляющие данный одномерный массив элементов.

Этот принцип действует во всех случаях. В том числе и при вызове приложения из командной строки.

Вызов приложения из командной строки с передачей ему в качестве параметров массива ОДНОТИПНЫХ (строковых) значений.

using System; class C1

{

static void Main(string[] args)

{

Console.WriteLine(“Values of parameters:”); for (int i = 0; I < args.Length; i++)

{

Console.WriteLine(“{0}: {1}”, i, args[i]);

}

}

}

Сначала создаётся консольное приложение (пусть под именем ComLine, в файле

ComLine.cs).

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

C:> csc /t:exe ConLine.cs

Результат деятельности транслятора размещается в .exe файле под именем ConLine.exe и также может быть запущен из командной строки с передачей строк символов в качестве входных параметров.

C:>ConLine qwerty asdfgh zxcvbn ok ok ok-k

В окне консольного приложения отобразится следующее множество строк:

Values of parameters:

0:qwerty

1:asdfgh

2:zxcvbn

3:ok

4:ok

5:ok-k

А теперь с использованием оператора foreach:

using System; class C1

{

static void Main(string[] args)

{

Console.WriteLine(“Values of parameters, using foreach:”); foreach (string arg in args)

{

Console.WriteLine(“{0}”, arg);

}

}

}

Запускаем:

C:>ConLine qwerty asdfgh zxcvbn ok ok ok-k

46

47

Получаем:

Values of parameters, using foreach: qwerty

asdfgh zxcvbn ok

ok ok-k

Полностью построенный массив можно передать в качестве входного параметра методу.

Пустая ссылка на массив может быть передана методу в качестве выходного параметра.

Например:

int[] myArray; // myArray == null PrintArray(myArray);

Можно также совместить передачу массива как параметра методу с предварительной инициализацией этого массива. Например:

PrintArray(new int[] {1, 3, 5, 7, 9});

In the following example, a string array is initialized and passed as a parameter to the PrintArray method, where its elements are displayed:

// cs_sd_arrays.cs using System;

public class ArrayClass

{

static void PrintArray(string[] w)

{

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

{

Console.Write(w[i] + “{0}”, i < w.Length - 1 ? “ ” : “”);

}

Console.WriteLine();

}

public static void Main()

{

//Declare and initialize an array: string[] WeekDays = new string []

{”Sun”,”Sat”,”Mon”,”Tue”,”Wed”,”Thu”,”Fri”};

//Pass the array as a parameter: PrintArray(WeekDays);

}

}

Вывод:

Sun Sat Mon Tue Wed Thu Fri

Спецификатор params

Неопределённое (переменное) количество (ОДНОТИПНЫХ!) параметров или список параметров переменной длины.

Это всегда последний параметр в списке параметров со спецификатором params. В выражении вызова метода должен располагаться либо список однотипных параметров (этот список преобразуется в массив значений), либо ссылка на

ОДНОМЕРНЫЙ массив значений определённого типа. using System;

class Class1

{

static void Main(string[] args)

{

47

48

f1(0,1,2,3,4,5);

f1(0,1,2,3,4,5,6,7,8,9,10);

f2(new int[,]{{0,1},{2,3}}, new int[,]{{0,1,2,3,4,5},{6,7,8,9,10,11}}); f2(new int [,]{{0,1},{2,3}});

}

static void f1(params int[] m)

{

Console.WriteLine(m.Length.ToString());

}

static void f2(params int[][,] p)

{

Console.WriteLine(p.Length.ToString());

}

}

Main в классе. Точка входа

Без статической функции (метода) Main невозможно построить выполняемую программу. Без явно обозначенной точки входа сборка не можен выполняться.

В сборке можно располагать несколько классов. Каждый класс располагает собственным набором методов. В каждом классе могут располагаться одноименные методы. В следующем примере объявляются три класса в одном пространстве имён. В каждом классе объявляется независимая точка входа. Три (!) СТАТИЧЕСКИЕ функции Main. Возможно и такое. При этом главная проблема - при компиляции надо явным образом указать точку входа.

Это можно сделать из командной строки при вызове компилятора. Например, так: c:\ csc /main:Class1.Class3 Example1.cs

Можно через диалог The Startup Object property среды разработки приложений (меню Проект-Свойства проекта, далее - General, Common Properties, <Projectname> Property Pages Dialog Box (Visual C#)), который обеспечивает спецификацию значений, которые явным образом НЕ ПРОПИСАНЫ в проекте. В разделе Startup object, надо раскрыть список классов и указать соответствующий класс.

Транслятор соберёт сборку, В которой будет обеспечена передача управления соответствующей функции Main (одной из трёх!).

using System; namespace Example1

{

//=============================================== public class Class1

{

// Спецификатор public нужен здесь. Третий класс. public class Class3

{

public static void Main()

{

string[] sss = new string[]{Class1.s.ToString(),”12345”};

Class1.Main(sss);

}

}

int d = 0;

public static int s;

static void Main(string[] args)

{

Class1 c1 = new Class1(); f1(c1);

c1.f2();

Class2 c2 = new Class2(); //c2.f2();

c2.f3();

48

49

string[] sss = new string[] {”qwerty”, c1.ToString()};

Class2.Main(sss);

}

static void f1(Class1 x)

{

//x.s = 100; s = 0;

Class1.s = 125; x.d = 1;

//d = 100;

}

void f2()

{

s = 0; Class1.s = 100; //this.s = 5;

//Class1.d = 125; this.d = 100;

d = 100;

}

}

//=============================================== class Class2

{

int d; static int s;

public static void Main(string[] args)

{

Class1.Class3.Main(); Class2 c2 = new Class2(); f1(c2);

c2.f2();

//Class1.Main();

}

static void f1(Class2 x)

{

//x.s = 100; s = 0;

Class2.s = 125; x.d = 1;

//d = 100;

}

void f2()

{

s = 0; Class1.s = 100; //this.s = 5;

//Class1.d = 125; this.d = 100;

d = 100;

}

public void f3()

{

s = 0; Class1.s = 100; //this.s = 5;

//Class1.d = 125; this.d = 100;

d = 100;

}

}

//===============================================

}

49

50

Структура также может иметь свою точку входа!

using System;

namespace defConstructors

{

struct MyStruct

{

static void Main(string[] args)

{

Console.WriteLine(“Ha-ha-ha”);

}

}

}

Создание объекта. Конструктор

Конструктором называется группировка кода, которой передаётся управление при создании объекта. Синтаксис объявления конструктора аналогичен обявлению метода. Те же спецификаторы доступа, имя, список параметров. Особенности конструктора заключаются в том, что:

конструктор НЕ ИМЕЕТ НИКАКОГО спецификатора возвращаемого даже void,

имя конструктора полностью совпадает с именем класса или структуры,

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

не существует выражения вызова для конструктора, управление в конструктор передаётся посредством выполнения специальной операции new.

ВC# ключевое слово new может быть использовано как ОПЕРАЦИЯ или как МОДИФИКАТОР.

new как операция используется:

для ссылочных типов (типов-ссылок) при создании объектов в уравляемой памяти

ипередачи управления конструкторам,

для

размерных типов

(типов-значений) при создании объектов в

СТЕКЕ.

Возможно, что при этом может потребоваться обращение к конструктору.

 

new

как модификатор

используется для сокрытия наследуемых из

базового

класса данных и методов. Об этом позже. После того, как рассмотрим подробнее принцип наследования.

Операция new

new операция используется для создания объектов и передачи управления конструкторам, например:

Class1 myVal = new Class1(); // Объект ссылочного типа. Создаётся в куче.

new также используется для обращения к конструкторам типа-значений (размерного типа), например:

int myInt = new int(); // Объект типа int размещается в стеке!

При определении объекта которое является значением имеет тот же самый эффект:

myInt ему было присвоено начальное значение 0, по умолчанию для типа int. Следующий оператор

int myInt = 0; // Для размерного типа аналогично.

Конструктор БЕЗ ПАРАМЕТРОВ (конструктор умолчания) обеспечивает инициализацию переменной предопределённым значением. Со списком предопределённых значений, которыми инициализируются объекты предопределённых типов, можно ознакомиться в Default Values Table.

У структуры конструктор умолчания (конструктор без параметров) НЕ ПЕРЕОПРЕДЕЛЯЕТСЯ! Для них объявляются только параметризованные конструкторы.

50

Соседние файлы в предмете Языки программирования