Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/16: Рейтинг темы: голосов - 16, средняя оценка - 4.88
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
1

Методы расширения многомерных и одномерных массивов

18.05.2012, 20:17. Показов 3230. Ответов 6

Author24 — интернет-сервис помощи студентам
Лишь недавно заметил, что методы расширения LINQ для многомерных массивов
C#
1
int[,] arr;
куда скуднее, чем для массивов обычных.
C#
1
int[]
Заглянув в MSDN, понял, что первые реализуют лишь обычный IEnumerable, который поддерживает куда меньше возможностей, чем его обобщенный товарищ. Хотелось бы узнать какое-то логическое объяснение сему, то есть что мешает многомерному массиву наследовать IEnumerable<T>. Спасибо.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.05.2012, 20:17
Ответы с готовыми решениями:

Приложение представляющее организацию многомерных вычислений многомерных массивов
Разработать приложение для Windows, представляющую организацию многомерных вычислений многомерных...

нужна помощь в С на тем одномерных и многомерных масивов
кто может и кому не очень трудно доходчиврс делать следующее задание 1.в одномерном масиве , с N...

Даны два одномерных массива разной размерности. Для каждого из заданных одномерных массивов выполнить: из
Даны два одномерных массива разной размерности. Для каждого из заданных одномерных массивов...

Расхождение многомерных массивов
Есть два многомерных массива: $arr1 = array ( 0 =&gt; array ('title' =&gt; 'Автослесарь'), 1 =&gt;...

6
Эксперт .NET
17791 / 12942 / 3381
Регистрация: 17.09.2011
Сообщений: 21,215
19.05.2012, 02:45 2
Цитата Сообщение от Lasur Посмотреть сообщение
первые реализуют лишь обычный IEnumerable, который поддерживает куда меньше возможностей, чем его обобщенный товарищ.
Возможности у этих интерфейсов одинаковы и заключаются лишь в одном: предоставлении итератора для обхода коллекции.

Другое дело, что все методы-расширения LINQ построены на работе именно с IEnumerable<T>, а не с IEnumerable.
Но это довольно легко "обойти", приведя массив к интерфейсу нужного типа:
C#
1
2
int[,] array = new int[5,2];
IEnumerable<int> iter = array.Cast<int>();
Дальше проблем с LINQ'ом не будет.
1
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
19.05.2012, 03:16  [ТС] 3
Цитата Сообщение от Lasur Посмотреть сообщение
первые реализуют лишь обычный IEnumerable, который поддерживает куда меньше возможностей, чем его обобщенный товарищ.
Цитата Сообщение от kolorotur Посмотреть сообщение
Возможности у этих интерфейсов одинаковы и заключаются лишь в одном: предоставлении итератора для обхода коллекции.
Я выразился не совсем верно, имея в виду список методов расширения.

За описание "обхода" спасибо, но вопрос остается прежним. Мне уже не впервой не удается понять тонкости реализации Array)
0
Эксперт .NET
17791 / 12942 / 3381
Регистрация: 17.09.2011
Сообщений: 21,215
19.05.2012, 11:52 4
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от Lasur Посмотреть сообщение
вопрос остается прежним.
Какой именно вопрос?
Если вы вот об этом
Цитата Сообщение от Lasur Посмотреть сообщение
что мешает многомерному массиву наследовать IEnumerable<T>.
то ответ прост: мешает ему то, что класс Array, от которого наследуются все массивы, не реализует интерфейс IEnumerable<T>, так как на момент его создания (.NET 1.0) обобщенний в языке еще не существовало.

Предвидя ваше замечание о том, что одномерные массивы реализуют этот интерфейс, скажу сразу: одномерные массивы с нулевым индексом, так называемые SZArrays (Single-dimensional, Zero-based arrays) являются особым случаем для компилятора и рантайма, так как одномерные массивы с нулевым индексом - фундаментальные структуры данных практически во всех языках программирования, потому компилятор обрабатывает эти массивы немного иначе с целью повышения их производительности. В частности, для одномерных массивов с нулевым индексом генерируется особый IL-код, где обращение к отдельным элементам происходит не через вызов виртуального метода конкретной реализации класса Array, а через прямую адресацию памяти, как происходит в языках типа С/С++. Поэтому, кстати, ступенчатые массивы в шарпе практически всегда выигрывают по производительности многомерным.
В общем, в шарпе SZArray - отдельный случай, причем используемый довольно часто, потому конкретно для этого случая в новой версии фреймворка добавили и реализацию нового интерфейса.

Общий же класс Array остался без изменений:
C#
1
2
foreach (var type in typeof(Array).GetInterfaces())
   Console.WriteLine(type);
System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
Это можно легко проверить, создав одномерный массив, но не с нулевым индексом:
C#
1
2
3
4
5
int[] lengths = { 0 };
int[] lowerBounds = { 1 };
var array = Array.CreateInstance(typeof(int), lengths, lowerBounds);
foreach (var type in array.GetType().GetInterfaces())
   Console.WriteLine(type);
Результат такой же, как и для класса Array:
System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
Как видим, обобщенного интерфейса тут нет и не предвидится.

А вот если создать SZArray, то дело принимает другой оборот:
C#
1
2
3
4
5
int[] lengths = { 0 };
int[] lowerBounds = { 0 };
var array = Array.CreateInstance(typeof(int), lengths, lowerBounds);
foreach (var type in array.GetType().GetInterfaces())
   Console.WriteLine(type);
System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
В целом же в ООП-языке многомерным массивам или массивам с ненулевой нижней границей отведена довольно узкая ниша применения, ограничивающаяся в основном студенческими лабами, интеропом с другими системами и обработкой матриц.
Ради такого никто не будет заморачиваться с перелопачиванием класса для реализации нового интерфейса.
3
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
19.05.2012, 13:28  [ТС] 5
Спасибо за столь полный ответ. Это именно то, что я спрашивал.
Но, признаться, впервые услышал про Zero-based arrays, и соответственно, появились новые вопросы.
Например, в одном из вопросов со StackOverflow написано, что
Nonzero-based arrays are not CLS-compliant
При этом вот такой код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[assembly:CLSCompliant(true)]
namespace Test
{
    [CLSCompliant(true)]
    public class Test
    {
        [CLSCompliant(true)]
        public static void Main()
        {
            int[] lengths = { 1 };
            int[] lowerBounds = { 1 };
            var array = Array.CreateInstance(typeof (int), lengths, lowerBounds);
        }
    }
}
не выдает никаких жалоб.
С другой стороны, в другом вопросе там же, утверждается, что
All arrays in C# are zero based.
Таким образом, единственное объяснение, которое приходит в голову, что это
C#
1
2
3
int[] lengths = { 0 };
int[] lowerBounds = { 1 };
var array = Array.CreateInstance(typeof(int), lengths, lowerBounds);
лишь обертка для Single-dimensional arrays, которая не наследует generic интерфейсы.
0
Эксперт .NET
17791 / 12942 / 3381
Регистрация: 17.09.2011
Сообщений: 21,215
19.05.2012, 14:41 6
Цитата Сообщение от Lasur Посмотреть сообщение
При этом вот такой код не выдает никаких жалоб.
К сожалению, атрибут CLSCompliantAttribute не всегда может точно определить соответствие метода/класса/сборки и т.д. правилам CTS.
В данном случае массив создается динамически, следовательно его размерность будет известна только во время рантайма, а атрибут используется на стадии компиляции.


Цитата Сообщение от Lasur Посмотреть сообщение
С другой стороны, в другом вопросе там же, утверждается, что
All arrays in C# are zero based.
Там этот же товарищ следующим предложением пишет:
As far as I know there is no way to create a 1 based array.
Что довольно красноречиво характеризует его знания о языке.

Цитата Сообщение от Lasur Посмотреть сообщение
Таким образом, единственное объяснение, которое приходит в голову, что это лишь обертка для Single-dimensional arrays, которая не наследует generic интерфейсы.
Скорее всего так и есть, но суть в том, что при создании массива, рантайм генерирует класс, наследующийся от Array, кроме случаев, когда массив является одномерным с нулевой нижней границей. В новой версии фреймворка этому отдельному случаю добавили поддержку обобщенного интерфейса, а сам класс Array трогать просто-напросто не стали. Да и как добавить реализацию обобщенного интерфейса, не делая сам класс Array обобщенным? А это, согласитесь, довольно серьезные изменения для такого фундаментального класса.
1
267 / 257 / 43
Регистрация: 18.03.2012
Сообщений: 506
19.05.2012, 14:50  [ТС] 7
Спасибо.
0
19.05.2012, 14:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.05.2012, 14:50
Помогаю со студенческими работами здесь

Создание многомерных массивов
День добрый, подскажите пожалуйста - раньше в си можно было сделать так: public struct MyStruct...

Сортировка многомерных массивов
Короче, происходит следующее: Браузер отказывается сортировать массив, элементами которого...

Обработка многомерных массивов
Массив (n,n) разбивается на четыре части, ограниченные главной и побочной диагоналями.Определить...

Обработка многомерных массивов
Создать многомерный массив 3x3 элементов.Сделать Разность по горизонтали. Три полученых результата...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru