Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 68
Текст из файла (страница 68)
Как указывает Джон Скит (дол Якее(), отделение логики сравнения от самого типа обеспечивает более высокую гибкость. Методы сортировки должны предоставлять перегрузку, принимающую тип, реализующий 1сотрагег/1соврагег<т>, который затем делегируется методу яогс для сравнения двух экземпляров. Такой дизайн, когда можно подставить алгоритм во время сортировки, представляет собой форму шаблона проектирования Я(га(еду (Стратегия), Синхронизация С необходимостью синхронизации доступа к массиву или типу коллекции, реализующему 1Со11есквоп, вы столкнетесь далеко не раа . Тип Яузеегк.
Актау реализует как 1со11ессвоп, таки 111зс. Одним из свойств 1со11ессаоп является 1зяупсьгопазеп, которое всегда возвращает Та1зе дла обычных массивов. Это объясняется тем,что обычные массивы не синхронизированы по умолчанию, поскольку это потребовало бы излишних расходов в тех случаях, когда синхронизация ненужна. Поэтому синхронизацией приходится управлять самостоательно. Совет. Если требуется синхронизация внутри коллекций, используемых в многопоточной системе, настоятельно рекомендуется испольэовать типы коллекций из яузсегз.со11есс1опз.
сопссггепс. эти типы были добавлены в .нет 4Д командой платформы параллельных вычислений М)сгозой, и их техника блокировки отлично настроена на обеспечение эффективности в многопоточных средах с параллелизмом. Также доступен интерфейс 1СоврагаЬ1е<Т> — обобщенная форма 1СотрагаЬ1е. 4 Темы синхронизации и параллелизма, а также многопоточности .)ЧЕТ Ргатпеяюг)г подробно раскрываются в главе 12. Массивы, типы коллекций и итераторы 255 Простейший способ управления синхронизацией связан с классом Я уз сею. Мопгсог, который обычно используется через ключевое слово 1осх.
Этот класс позволяет запросить встроенную блокировку синхронизации на объекте . Однако вместо запроса блокировки на самом объекте массива следует запрашивать блокировку на объекте 10о11ессгоп.зупскоос. На заметку! Блокировку можно запрашивать на любом объекте, имеющем ссылку в С[К. Каждый объект оснащен "лениво" создаваемым блоком синхронизации, содержащим переменную блокировки, которой СЬК управляет внутренне, когда я узкая.
мопггог пытается запросить блокировку. Многие массивы и реализации коллекций могли бы возвращать ссылку на действительный контейнер через свойство 10011естгоп. ЯупсРоош но по разным причинам не делают этого. 10о11ессгоп. Бупсйоог предоставляет общий способ для синхронизированного доступа как к массивам, так и к коллекциям.
Синхронизация еще будет рассматриваться в разделе "Синхронизация коллекций", когда речь пойдет об интерфейсе 10о11ессгоп. Сравнение векторов и массивов Интересно отметить, что з СЬК поддерживаются два специальных типа для обращения с массивами з коде С». Если массив является одномерным, и его нижняя граница равна О, что обычно верно для массивов Саз, то СЬК использует специальный встроенный тип, называемый зеки(ором. который на самом деле является подтипом Буз сея.
Актау. В среде СЬК предусмотрены специальные инструкции 1Ь, предназначенные для прямого обращения с векторами. Если массив является многомерным, то тип вектора СЬК не исполъзуется, а вместо него применяется обычный объект массива. Чтобы продемонстрировать это, взглянем на код 1Ь, сгенерированный для следующего короптого примера: рсЬ11с с1ззз БпсгуРоглг ( зсзсгс чого Мага() ( глс чз1 = 1234 1пс пенуэ1; глс[) чессог = лен гпс[1]1 гпс[,] зггау пеи 1лс[1,1); чесгог[0) чз1; аггау[0,0] = ча1; пеича1 = чессог[0]к ленуа1 = аггзу(0,0]; Посмотрим на код 1Ь, сгенерированный для метода Маго: .теспоо рггчзте Ьгт(еЬуз10 зсаг1с чогб Мага() с11 аэпзсес ( .епкгуроглк УУ Сот(е згге 46 (Ох2е) .жэхзсасх 4 .1осз1з глгс ([О] гпс32 ча1, [1) 1пс32 пенуз1, Подробнее о Бузсет.Молгсоги прочих приемах синхронизации читайте в главе 12.
Массивы. объявленные э синтаксисе массивов Са, всегда имеют нижнюю границу О. Если нужен массив с ненулевым начальным индексом, его экземпляр должен создаваться с помощью метода Яуэсеи.Актау.сгеасе1лзсэпсе () . 256 Глава 0 32, бпг32) 11. 0020 11 0021 11 0022 1Ь 0023 1Ь 0024 1Ь 0025 1Ь 0028 1Ь 0027 11 002с 11 002б (/ епб ог Обратите внимание иа различия в использоваиии двух массивов СВ. В строке 1ь 0005 инструкция пезагг создает экземпляр, представленный переменной чесгог. Многомерный массив, хранящийся в переменной аггау, создается в строке 1Ь 000б.
В первом случае операциявыполняется с помощью низкоуровневой инструкции П., а во втором случае — с помощью вызова обычного конструктора. Лизлогичио при обрэщеиии к элементам для вектора используются 1Ь-ииструкции я се1ев и 1бе1ев. соответственно, в строках 11, 0015 и 11, 0022, тогда как для многомерного массива — обычные вызовы методов. Поскольку поддержка вектора обрабатывается специфическими инструкциями 1Ь, предусмотренными специально для векторов. вполне уместно предположить, что использование векторов более эффективно, чем миогомериых массивов, даже несмотря иа то, что экземпляры обоих унаследованы от Зуягев.
))ггау. Многомерные прямоугольные массивы В СЗ и СЬК имеется прямая поддержка многомерных массивов, которые также иазываются прямоугольными массивами. В СФ очень легко объявить массив с несколькими измерениями. Для этого понадобится внутри квадратных скобок просто перечислить через запятую раэмериости массива, как показано в следующем примере: 1Ь 0000 1Ь 0001 1Ь 0003 1Ь 0004 1Ь 0005 1Ь 000а 1Ь ОООЬ 1Ь ОООс 1Ь 000б 1Ь 0012 1Ь 0013 1Ь 0014 11 0015 11, 0016 1Ь 0017 11 0018 11 0019 1Ь 001а 11. 001Ь [2] 1пс32[] 'чессог', [3] 1пг32[0...,0...] 'аггау') пор 1бс.14.я 123 яг1сс.О 1бс.14.1 пеязгг [вясог11)з]Буягев.1пс32 яг1ос.2 1бс.14.1 1бс.14.1 пеяс)з) Ьпясапсе чоаб 1пс32[О...,О...]зз.сгог[1пг яг1ос.З 1с)1ос.2 1бс.з.4.0 1б1ос.О ясе1ев.
14 1б1ос.З 14)с.14.0 1бс.14.0 1б1ос.О са11 Ьпясапсе чоьб Ьпп32[0...,0...]ззЯес[1пс32, 1пс32, 1пг32) 1б1ос.2 1бс.14.0 1бе1ев.14 яг1ос.1 1б1ос.З 1бс.з.4.0 1с)с.14.0 са11 Ьпясапсе 1пс32 Ьпс32[0...,0...]зз6ес[1пг32, 1пг32) яг1ос.1 гес вес)зоб ЕпггуРоапг з знаап Массивы, типы коллекций и итераторы 257 озап9 Яуягевт роь11с с1аяя ЕпогуРоЬпс ( ягагус готт) МаЬп() ( 1пт [, ) т еооув1 = пеи 1пк (5, 3); 1пс [, ) Геопав2 = ( (1, 2, 3), (4, 5, 6), (7, 8, 9) )) тогеас)т( Ьпк 1 кп Геооув2 ) ( Оопяо1е.ыг1кеЬЬпе( 1 )т ) Относительно использования прямоугольных массивов следует отметить несколько моментов. Все обращения к этим массивам сводятся к вызову методов сгенерированного СЬК ссылочного типа, и встроенный тип вектора здесь не участвует.
Обратите внимание на два объявления. В обоих случаях при объявлении типа указывать размер каждого измерения не нужно. Это объясняется тем, что массивы тнпизируются на основе типа элементов и размерности [ранга). Однако при создании экземпляра типа массива указывать размер измерений обязательно.
В данном примере это сделано двумя разными способами. При создании т иопава размеры указаны явно, а при создании т иопйв2 компилятор определяет размеры на основании выражения инициализации. В примере все элементы массива выводятся в цикле уогеас)т. Этот цикл проходит по всем элементам массива, строка за строкой. Той же цели можно достигнуть с помощью двух вложенных циклов уог, и так бы пришлось поступить в случае, когда нужно пройти по элементам массива в любом другом порядке. Имейте в виду, что свойство )(ггау. Ьепос)т возвращает общее количество элементов в массиве. Чтобы получить размер каждого измерения, понадобится применить метод Аггау. ВеСЬепдг)т, указав интересующее измерение.
Например, итерацию по элементам массива можно выполнить с помощью следующего кода, который дает тот же результат, что и предыдущий: озапо Вуясев; ро511с с1азя Ептгуроапс ( ясас1с гога Мака() ( 1пс(,) Сиоотв = ( (1, 2, 3), (4, 5, б), (7, 8, 9) )т лог( Ьпс 1 = От 1 != геоотв<зеГЬепос)т(О) т ++1 ) ( гог( Ьпг 3 = От 3 != геоотв.песьепсгп(1)т +е3 ) ( сопяо1е.игагеь1пе( гиооав[1,3) )т лог( Ьпг г = тиоОЬв.сеГЬоеегВоопт((О)т <= теоотв.сегпррегвоопо(О); ++1 ) ( тот( Ьпг 7 = Ьиоотв.сегьоеегВоопт)(1)т 3 <= с оотв.аесоррегвоопт((1)т ) ( Оопяо1е.игусеЬгпе( Геооув(1,3) ); ) ) 288 глава 9 Для наглядности было показано.
как выполнять итерацию по размерностям массива, двумя разными методами. Первый метод предполагает, что нижняя граница каждого измерения равна О, а второй — нет. При всех вызовах ЯегьепдСЬ. Яегпррегвоцпг] и Яегьонегвоцпс( должен быть указан номер интересующего измерения, начиная с нуля. На заметку! Все массивы, создаваемые внутри С» с использованием стандартного синтаксиса объявления массивов, будуг иметь нижнюю границу индекса, равную О. Однако если зы имеете депо с массивами, используемыми з математических целях, а также с массивами, пришедшими из сборок, написанных на других языках, то нужно учитывать, что нижняя граница индекса может и не быть равной О.
При обращении к элементам многомерного массива компилятор генерирует вызовы методов пес и яес, которые подобны яессгз1це и яесчз1це. Эти методы перегружены для приема переменного списка целых чисел, специфицирующих порядок каждой размерности массива.
Для отображения многомерных массивов на математические концепции прямоугольный массив является наиболее естественным и предпочтительным. Однако создание метода, аргумент которого может быть массивом переменной размерности, является непростой задачей, поскольку необходимо принимать аргумент типа Я уз сеп.
Актау и динамически обращаться с его размерностью. Размерность массива можно получить с помощью свойства Актау. Вапх. Поэтому создание обобщенного для размерности кода непросто, из-за синтаксической сложности обращения к элементам массива через вызовы методов Я уя Сеп.
Актау, хотя это и вполне возможно. Кроме того, наиболее обобщенный код манипуляций с массивами должен учитывать возможность существования ненулевых границ индексов по отдельным размерностям. Многомерные зубчатые массивы Если вы пришли из мира С/С++ или бата, то, скорее всего, уже знакомы с зубчатыми (]аллеб] массивами, поскольку эти языки не поддерживают прямоугольных массивов, как это делает С№. Единственный способ реализации многомерных массивов в этих языках — создавать массивы массивов, а именно это и представляют собой зубчатые массивы.
Однако поскольку каждый элемент массива верхнего уровня является отдельным экземпляром массива, каждый экземпляр массива верхнего уровня может быть любого размера. Поэтому такой массив не обязательно прямоуголен — отсюда и термин зубчагпые массивы. Синтаксический шаблон объявления зубчатого массива в С№ подобен тому, который принят в С++ и ]эта.
В следующем примере показано, как развернуть и использовать зубчатый массив: пяспп Яуясеп; цяспз Яуясеп.техс; рпЬ11с с1аяя Япггуго1пС ( ягаггс чосд Магп() ( 1пс(!() ]аппес = пен гпг[3)[]г ]азсес((0] = пен ].пС(] ( 1, 2); ]зудел(1] = пен 1пС() (1, 2, 3, 4, 5); ]апуес((2] = пен пС(] (б, 5, 4)г Гогеасп( 1пС(] аг сп ]адрес ) ( Ясг1пдВп]1цег яЬ = пен ЯггспдВп11цег()г Массивы, типы коллекций и итераторы 259 Гогеасп( Тпе и Тп аг ) ( зЬ.Аррепг)уогаак( "(0) ", и ); ) сопэа1е.игтсеьтпе( зь.тсзсг1пд() ); ) Сопзо1е.нг1ееьтпе()г Гог( 1пс 1 = 0; 1 < Эаддес.Ьепдьпг +41 ) ( Бег1пдВи11оег зЬ пен Бсг1пдвс11г)ег(); гог( 1пс О = 0; б < ]аддео(1].ьепдсьг 4+! ) ( зЬ.Аррепг)гогаак( "(0) ", баддес([].](б] Сопэо1е Нг1ее11пе ( зЬ.Тозег1пд() Как видите, распределение и создание зубчатого массива несколько сложнее, чем массива прямоугольного, поскольку нужно обрабатывать распределения всех подмассивов индивидуально, в то время как прямоугольный массив распределяется за один прием.
Обратите внимание на "зубчатый" вывод, который объясняется разными размерами каждого подмассива: 1 2 12345 654 В данном примере демонстрируются два способа выполнения итерации по массиву — просто чтобы показать синтаксис доступа к индивидуальным элементам внутри зубчатого массива и его отличие от обращения к элементам прямоугольного массива.














