Здравствуйте, Аноним, Вы писали:
А>это называется "перекуем баги архитектуры в фитчи"
Это способ избавиться от комбинаторного взрыва.
Глаза у меня добрые, но рубашка — смирительная!
Re[8]: int[].Add
От:
Аноним
Дата:
25.11.10 07:21
Оценка:
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
А>>основной вопрос: зачем показывать то, что мне недоступно для использования?
A>Простите, у меня впечатление что вы первый день программируете или просто тролль.
думаю, проблема в другом — вы мыслите с точки зрения программиста, а я пользователя
поэтому вариант, что каждый останется при своем мнении мне видится оптимальным
Здравствуйте, adontz, Вы писали:
A>>>Коллекция не всегда создаётся и заполняется в рамках одного метода, VD>>Вот это у тебя косяк в дизайне, да. Старайся так не делать.
A>Аргументы будут?
Для меня это настолько очевидно, что я даже затрудняюсь найти доходчивое объяснение.
Пока мы меняем коллекцию внутри метода — это проблемы реализации одного метода. Когда мы растягиваем этот процесс по нескольким методам, то начинаем иметь дело с неинкапсулированным состоянием. А это уже не хорошо. Я конечно понимаю, что на языках где нет локальных функций подмывает разбить код (произвести его декомпозицию) на отдельные (хотя бы private) методы. Но все же это плохо. Решаем одну проблему — создаем другую.
A>>> так что будьте знакомы — http://en.wikipedia.org/wiki/Interface_segregation_principle VD>>Вообще-то конечно жить лучше своими мозгами, но все же ты бы прежде чем давать ссылку почитал бы ее. Это статья как раз о том почему в IList не должно быть Insert().
A>Вот давай без прыжков в сторону. Речь шла об использовании конкретного типа вместо интерфейса.
Какие прыжки? Изначально мы говорили о том, что интерфейсы коллекций в дотнете криво спроектированы. Ты дал ссылку на кошерное обоснование того, что интерфейсы должны быть маленькими и специализированными, а не толстыми и всеобъемлющими.
А вот про конкретные типы я там ничего не углядел.
Ты наверно перепутал этот принцип с простой идеей, что возвращать конекртные изменяемые коллекции из методов не кошерно. С этим я в общем-то согласен. Хотя тоже не вижу в этом ничего плохого, если возвращается копия.
A>>>Зачем я не сообщаю всем подряд тип класса конкретной реализации? Мне что, действительно придётся это объяснять? VD>>Зачем кому-то рассказывать о внутренней реализации?
A>Вот именно, зачем?
Дык ты это и предлагаешь. Причем думаешь, что если спрятать изменяемый индексируемый список за интерфейсом, то это решит проблему. Не решит. Ты конечно получишь гипотетический бенефит от того, что сможешь сменить реализацию коллекции не трогая другого кода. Но плюешь на куда более серьезную проблему размазывания императивного алгоритма по разным методам. Императив нужно инкапсулирвоать.
И кстати, если бы ты передавал именно IMutableList, то по сигнатуре метода уже можно было бы понять, что он будет менять этот список, а значит с данным методом нужно быть как можно акуратнее. А так ты передаешь IList и в те методы что просто нуждаются в списке, и в те, что собираются его изменять. Это явное использование абстракции на вред себе любимому. Это ничем не отличается от передачи IMutableList методу который не собирается менять данные.
VD>>Есть один отличный принцип который я почерпнул из ФП. Если речь идет об обработке данных, то лучше стараться всегда делать ее так чтобы не изменять исходных данных. А к императиву прибегать только когда это оправдано соображениями производительности или иными весомыми соображениями. Тогда весь код по работе с коллекциями резко уходит в глубь методов, а наружу начинают торчать списки (в немерле list[T]) и массивы (копии данных). При этом вопросов с абстрагированием или связанностью не возникает в принципе. Мы ведь всегда работаем с "отключенными" данными (копиями). VD>>Так что если я вижу в коде передачу изменяемой коллекции (даже интерфейса) в другой метод, то это сразу же меня настораживает.
A>Влад, как эти замечательные рассуждения коррелируют с каким-либо байндингом?
Зависит от реализации оного.
A>А, ну да, никак. На Nemerle или ASP.Net мир клином не сошёлся. Бывает необходимо обмениваться изменяемыми коллекциями и это не всегда плохой дизайн, как ты почему-то думаешь.
Дык и неизменяемыми структурами данных можно обмениваться без проблем. В конце концов любое изменение можно рассматривать как удаление старого объекта и вставку нового. Так что на входе имеем список с исходными объектами, на выходе новый где часть объектов старые, а часть новые (ставленные или замененные). При этом очень легко сделать между ними diff и получить третий список содержащий только изменения.
Потом на ГУИ свет клином не сошелся. ГУЯ не так много в серьезных задачах. Обработка данных обычно занимает куда больше места и времени (программиста). И тут вопросы биндига уже не будут актуальны.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
A>>>И как вы предлагаете это реализовать? IList<> может быть поиницилизирован очень далеко, вообще в другом модуле. С какой стати компилятору запрещать вам вызывать метод? А>>как реализовать это вопрос другой.
A>Это основной вопрос. Если вы не можете предложить ничего лучше, то не ругайте то, что есть.
Я тоже считаю что в интерфейсах коллекций бардак. Другое дело — я привык к нему. Предлагать ничего не буду, не готов прямо сейчас, да и бестолку это. Но уверен, что можно было сделать лучше.
Здравствуйте, Ikemefula, Вы писали:
I>>>Для чего нужны IList/IList<> в массивах ? _FR>>Например, для того, что бы можно было бы написать обобщённый метод сортировки, принимающий IList/IList<>. I>Это какое то мелкое преимущество
Мне жаль, если ваша фантазия не позволяет вам отыскать других А они есть.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, VladD2, Вы писали:
VD>Не выдумывай. Никакого экспоненциально роста не будет. Будте грамотный дизайн. А то что есть — это бардак.
Влад, если бы сам сел и внимательно расписал все классы, то не стал бы спорить. Впрочем с твоим опытом проектирования необходимости в ручке и бумаге быть не должно, так что ты меня попросту удивляешь.
Ладно, я сделаю эту работу за тебя. Для полноты картины и в назидание потомкам.
public interface IEnumerable<T>
{
IEnumerator<T> GetEnumerator();
}
public interface ICollection<T> : IEnumerable<T>
{
bool Contains(T item);
bool CopyTo(T[] array, int arrayIndex);
int Count {get;}
}
// Это ничего, что Clear Вместе с Add/Remove или ещё делить?
// Где обоснованная граница? Бывает же, что Add/Remove можно, а Clear - нельзя.
// А ещё бывает, что можно Add, но нельзя Remove.public interface IMutableCollection<T> : ICollection<T>
{
void Clear();
void Add(T item);
bool Remove(T item);
}
// Опять таки, всегда ли делать доступным IndexOf?
// Метод весьма сомнительный, в колелкции с неуникальными элементами вводит в заблуждение,
// лучше уж IList<int> IndicesOf(T item), но такой метод плох в коллекции с уникальными элементами.public interface IList<T> : ICollection<T>
{
int IndexOf(T item);
T this[int index] { get; }
}
public interface IMutableAddRemoveList<T> : IList<T>, IMutableCollection<T>
{
int Insert(int index, T item);
bool RemoveAt(int index);
}
public interface IMutableModifyList<T> : IList<T>
{
// Это полностью новое свойство, нельзя доопределить сеттер.
T this[int index] { get; set; }
}
////////////////////////////////////////////////////////////////////////////////
// Реализация по умолчанию, как List<T>public class MutableAddRemoveList<T> : IMutableAddRemoveList<T>
{
...
}
// Реализация по умолчанию, как List<T>public class MutableModifyList<T> : IMutableModifyList<T>
{
...
}
// Реализация по умолчанию, как List<T>
// Copy+Paste их двух предыдущих классов.public class MutableList<T> : IMutableAddRemoveList<T>, IMutableModifyList<T>
{
...
}
Уже три класса вместо одного, и двойное повторение кода. В два раза больше кода, полученного обычной копипастой. Сомнительный признак хорошей архитектуры. И заметь, есть ещё куча возможностей улучшить архитектуру разбив интерфейсы на более мелкие! Теперь добавим сюда observable collections и разные другие фенечки и получим ещё одну волну увеличения количества классов и копий кода. В Си++ эта проблема решалась: MutableList<T> унаследовался бы от MutableAddRemoveList<T> и MutableModifyList<T>. В .Net эта проблема не решается непосредственно.
Кроме того, что делать с ситуациями, когда доступно операции величина не постоянная? Вот скажем у меня коллекция связана с каким-то хранилищем (БД или что-то ещё) и менять её (писать в хранилище) можно только наложив блокировку. То есть в каких-то случаях (когда блокировки нет) IsReadOnly вернёт true, а Add(T) выбросит InvalidOperationException, а в каких-то других случаях IsReadOnly вернёт false и Add(T) отработает штатно. Как такие сценарии сочетаются с идеей fine grained interfaces?
То есть, если резюмировать, то что ты предлагаешь вызывает бурный рост количества сущностей, кучу копирования кода при реализации коллекций и лишь частичное покрытие возможных сценариев.
Здравствуйте, samius, Вы писали:
A>>Это основной вопрос. Если вы не можете предложить ничего лучше, то не ругайте то, что есть. S>Я тоже считаю что в интерфейсах коллекций бардак. Другое дело — я привык к нему. Предлагать ничего не буду, не готов прямо сейчас, да и бестолку это. Но уверен, что можно было сделать лучше.
Здравствуйте, samius, Вы писали:
A>>Без множественного наследования — нельзя. S>И для чего оно тут?
Потому что иначе получишь комбинаторный рост количества реализаций от количества интерфейсов. enumerable/readonly/resizable — это три разных признака. И тебе надо сделать какую-то системную реализаую для колелкции размер которой менять нельзя, но можно менять элементы. Без множественного наследования будешь выписывать все варианты копипейстом. Можно привести фундаментальный и более просотой пример — System.Stream vs. istream/ostream.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Аноним, Вы писали:
А>>конкретные вещи: А>>есть розетки на 360, а есть на 220В. Розетка в данном случае — это интерфейс. А>>Я не могу вставить вилку 220 в 360. А>>Считай, что метод Add это вставки вилки в розетку
_FR>А кто вам _обещал_ какую-то конкретную розетку или вилку? Чем одна розетка\вилка лучше другой? Ничем, они равноправны. А переходники у любого _квалифицированного_ путешественника должны быть в наличии. Из приведённого вами примера виднен лишь недостаток квалификации
_FR>Продолжайте, весилите публику в том же духе.
по сути ответа на конкретный пример не услышал — следовательно, сказать нечего
Здравствуйте, samius, Вы писали:
A>>Массив в таком случае должен реализовывать два интерфейса — для перечисления и для изменения значения элемента и не должен реализовывать интерфейс для смены размера. Как несложно посчитать всего существует 3 + 3*2 + 1 = 10 разных комбинаций. То есть если уж ввёл интерфейсы, то будь добр реализовать 10 разных стандартных коллекций на все случаи жизни. S>Я бы удовлетворился стандартными контейнерами. Мне не нравится что интерфейсы не fine-grained.
Смысла в это всё равно нет, потому что я лично сам встречался со случаями когда коллекция ReadOnly/FixedSize иногда. Интерфейсами такое не обозначить.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, samius, Вы писали:
A>>>Смысла в это всё равно нет, потому что я лично сам встречался со случаями когда коллекция ReadOnly/FixedSize иногда. Интерфейсами такое не обозначить. S>>Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
A>Проще свойствами. И если они как-то нелогично работают у массива это не значит что путь в целом неправильный.
Мне сложно назвать правильным путь, в рамках которого одна из наиболее часто используемых сущностей ведет себя нелогично, либо логика ее работы не очевидна, а на счет остальных нельзя сказать, можно ли изменять их элементы.
Мне не нравится это решение, но я готов с ним мириться и не собираюсь наводить во фреймворке порядок.
Здравствуйте, Qbit86, Вы писали:
_FR>>Тогда это разговор примерно такого же уровня, как "Мне нужен класс Form у которого небыло бы свойства Caption, поскольку он мне не нужен, а раз такого нет — архитектура дотнета отстой". Q>Да нет же, архитектура Дотнета действительно отстой
Здравствуйте, _FRED_, Вы писали:
_FR>Нет уж, сказали — покажите. Пока что я вижу возможность такого либо специализированной под массив, то есть отдельной, реализиции, либо копированием массива в список. И то и другое по сравнению с тем, что есть, выглядит намного хуже. Так как — сумеете ответить за свои слова и прести реализацию ReadOnlyCollection<>, поддерживающую как IList<> так и массив или не сумеете?
IList<> в ReadOnlyCollection есть зло !
В прынцыпе, в массиве IEnumerable можно оставить, шоб вообще всё было сильно
interface IEnumerable<T> : IEnumerable
{
...
}
class Array<T> : IEnumerable<T>
{
...
}
interface IReadonlyCollection<T> : IEnumerable<T>
{
...
T[] ToArray(); // заместо CopyTo
...
}
interface ICollection<T> : IReadonlyCollection<T>
{
...
}
interface IList<T> : ICollection<T>
{
...
...
}
class ReadOnlyCollection<T> : IReadonlyCollection<T> // и никаких IList
{
T[] _items;
...
public ReadOnlyCollection(IEnumerable<T> items)
{
// нынешняя ReadonlyCollection этого не делает и приходится вызывать Enumerable.ToList() самому или следить за геморроем
Copy(items);
}
...
}
Здравствуйте, _FRED_, Вы писали:
I>>В прынцыпе, в массиве IEnumerable можно оставить, шоб вообще всё было сильно
_FR>Спасибо, но ваш пример убедительно показывает вашу некомпетентность в обсуждаемом предмете, что и требовалось доказать.
Весомый аргумент
>Копирование в конструкторе ReadOnlyCollection<> и прочие утверждения безумны.
ReadOnlyCollection в нынешней реализации никакой не ReadOnlyCollection, он меняется при чем ты даже не знаешь когда.
А копирование двух массивов вобщем то не шибко дорогая операция.
Заметь — ты не можешь не только критиковать, но и свою версию пояснить не в состоянии.
Здравствуйте, _FRED_, Вы писали:
_FR>Если вы открыто высказываете мнение об ошибках проектироващиков, но при этом не в курсе, как проктировалось осуждаемое вами и почему оно именно такое — то не оскоррбляться надо, когда вам рассказывают, как дело было и почему и зачем вышло так,
Я лично сомневаюсь что ты знаешь как проектировалось осуждаемое нами, тебя нет ни в списке авторов дизайна ни в списке авторов книг по оному.
"а мотать на ус, испытывая чувство благодарности за то, что кто-то тратит время, рассказывая вам то, что вы ранее не знали"
Здесь не тот случай, что кто то чего то не знает, а наоборот, знают и более того, имеют свое мнение.
А ты вот объяснений внятных дать не можешь, внятно покритиковать — тоже не можешь.
Вобщем испытывай чувство благодарности когда ктото тратит своё время показывая тебе упущения в ведении дискуссии
[...] А>как реализовать это вопрос другой. я говорю про то, что если у вас есть кнопка на телефоне Позвонить, то она должна звонить, а не говорить мне "я не могу это сделать, т.к. кнопку воткнули для совместимости с общим модулем управления клавиатурой"
Возьмите свой мобильный телефон (или у друга если нет своего... Если нет друга, то купите! Телефон естественно). Выньте из него аккумулятор и нажмите кнопку Позвонить. Ну что, позвонил?
Здравствуйте, MozgC, Вы писали:
MC>Можно показать, где Рихтер об этом писал, а то я и второе и третье издание читал, и такого не припомню. Если я прав, то может стоит удостовериться сначала, написано ли там такое, прежде чем оскорблять человека, говоря о его некомпетентности и о том, что "классику все-таки по диагонали читать не следует"?
Он имеет ввиду книгу, в которой Рихтер выступил в основном комментатором и в которой авторы не раз посыпали голову пеплом из за дизайна первых версий дотнета
Писал на самом деле не Рихтер, а Krzysztof Cwalina. "Design guidelines."
Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, MozgC, Вы писали:
MC>>Можно показать, где Рихтер об этом писал, а то я и второе и третье издание читал, и такого не припомню. Если я прав, то может стоит удостовериться сначала, написано ли там такое, прежде чем оскорблять человека, говоря о его некомпетентности и о том, что "классику все-таки по диагонали читать не следует"?
I>Он имеет ввиду книгу, в которой Рихтер выступил в основном комментатором и в которой авторы не раз посыпали голову пеплом из за дизайна первых версий дотнета I>Писал на самом деле не Рихтер, а Krzysztof Cwalina. "Design guidelines."
We also decided that arrays will return true from IsReadOnly, but will actually allow setting values using the indexer (which we are trying to fix in RTM as it does not work today).
Здравствуйте, Аноним, Вы писали:
A>>А какова альтернатива? А>чтобы у меня были доступны методы которые я могу всегда использовать
И как вы предлагаете это реализовать? IList<> может быть поиницилизирован очень далеко, вообще в другом модуле. С какой стати компилятору запрещать вам вызывать метод?
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, Аноним, Вы писали:
А>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн?
Q>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern».
это называется "перекуем баги архитектуры в фитчи"
Здравствуйте, Аноним, Вы писали:
A>>И как вы предлагаете это реализовать? IList<> может быть поиницилизирован очень далеко, вообще в другом модуле. С какой стати компилятору запрещать вам вызывать метод? А>как реализовать это вопрос другой.
Это основной вопрос. Если вы не можете предложить ничего лучше, то не ругайте то, что есть.
А>конкретные вещи: А>есть розетки на 360, а есть на 220В. Розетка в данном случае — это интерфейс. А>Я не могу вставить вилку 220 в 360. А>Считай, что метод Add это вставки вилки в розетку
Приведение массива к интерфейсу это использование переходника для вилки. С переходником вставить сможешь.
Здравствуйте, Аноним, Вы писали:
А>[skipped] А>много казуистики.
То есть по сути вам ответить таки нечего
А>конкретные вещи: А>есть розетки на 360, а есть на 220В. Розетка в данном случае — это интерфейс. А>Я не могу вставить вилку 220 в 360. А>Считай, что метод Add это вставки вилки в розетку
А кто вам _обещал_ какую-то конкретную розетку или вилку? Чем одна розетка\вилка лучше другой? Ничем, они равноправны. А переходники у любого _квалифицированного_ путешественника должны быть в наличии. Из приведённого вами примера виднен лишь недостаток квалификации
Продолжайте, весилите публику в том же духе.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, samius, Вы писали:
S>>Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
A>Вообще-то, есть свойство IsFixedSize
У другого интерфейса. Я просил без даункаста
Здравствуйте, _FRED_, Вы писали:
_FR>Тогда это разговор примерно такого же уровня, как "Мне нужен класс Form у которого небыло бы свойства Caption, поскольку он мне не нужен, а раз такого нет — архитектура дотнета отстой".
Да нет же, архитектура Дотнета действительно отстой :)
Глаза у меня добрые, но рубашка — смирительная!
Re[6]: int[].Add
От:
Аноним
Дата:
25.11.10 10:11
Оценка:
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Аноним, Вы писали:
А>>>>конкретные вещи: А>>>>есть розетки на 360, а есть на 220В. Розетка в данном случае — это интерфейс. А>>>>Я не могу вставить вилку 220 в 360. А>>>>Считай, что метод Add это вставки вилки в розетку
_FR>>>А кто вам _обещал_ какую-то конкретную розетку или вилку? Чем одна розетка\вилка лучше другой? Ничем, они равноправны. А переходники у любого _квалифицированного_ путешественника должны быть в наличии. Из приведённого вами примера виднен лишь недостаток квалификации
_FR>>>Продолжайте, весилите публику в том же духе.
А>>по сути ответа на конкретный пример не услышал — следовательно, сказать нечего
_FR>Я тоже не услышал выше ответов по сути. Однако вы что-то всё-таки в ответ, не по сути, но сказали. Следовательно, ваш вывод о том, что сказать нечего мне — ошибочен. Качайтесь :о)
А вы, я смотрю, любитель казуистики. Я вам привожу конкретику, а вы мне про "Чем одна розетка\вилка лучше другой?".
Не надо много писать мне философии, давайте кратко и по делу.
Если непонятен мой позыв, повторю: не надо человеку показывать возможность что-то сделать, но при этом не делать этого.
Здравствуйте, _FRED_, Вы писали:
_FR>"Что-то" ошибается. Дело в том, что IList.IsReadOnly и ICollection<>.IsReadOnly — несколько разные IsReadOnly. И это совсем не сложно. Если вы этого раньше не знали, не нужно оправдывать незнание тем, что это сложно и не нужно, а так же опасно.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, samius, Вы писали:
_FR>Вот это — "пять", как говорится. То есть "неочевидная логика" в вашей логике "нелогична" И всего навсего из-за пропущенных/забытых глав из Рихтера. Потрясающая логика — рассуждать о логичности того, с чем впервые столкнулся. ИМХО, рассуждая таким путём _очень_ сложно не ошибиться.
Можно таки ссылку на главу у Рихтера, проливающую свет на данный вопрос?
Здравствуйте, _FRED_, Вы писали:
I>>>>Для чего нужны IList/IList<> в массивах ? _FR>>>Например, для того, что бы можно было бы написать обобщённый метод сортировки, принимающий IList/IList<>. I>>Это какое то мелкое преимущество
_FR>Мне жаль, если ваша фантазия не позволяет вам отыскать других А они есть.
То есть примеров у тебя нет и ты решил удариться в словоблудие ?
We also decided that arrays will return true from IsReadOnly, but will actually allow setting values using the indexer (which we are trying to fix in RTM as it does not work today).
MC>Спорное решение..
Сдается им пришлось из за дизайна первых версий выкручиваться.
Здравствуйте, MozgC, Вы писали:
MC>Здравствуйте, _FRED_, Вы писали:
_FR>>Я, признаться, удивлён: говорить о том, что коллекции сделаны не лучшим образом и не знать базовых интерфейсов коллекций _FR>>Единственная коллекция с таким свойством — массив, и специально для него было сделано IList.IsFixedSize Property. Об этом, если не ошибаюсь, даже Рихтер писал. Классику всё-таки по диагонали читать не следует, что бы не задавать потом подобных вопросов.
MC>Можно показать, где Рихтер об этом писал, а то я и второе и третье издание читал, и такого не припомню. Если я прав, то может стоит удостовериться сначала, написано ли там такое, прежде чем оскорблять человека, говоря о его некомпетентности и о том, что "классику все-таки по диагонали читать не следует"?
Если он об этом и не писал, то это никак не отменяет факта того, что данные вещи требуется знать, более того, вступая в спор о правильности проектирования коллекций. Не из литературы, так из десятиминутного эксперимента. Это же настолько базовые вещи. Вам нужно поработать с интерфейсом, имеющим ряд свойств (не два-три десятка, а столько, что можно пересчитать по пальцам одной руки). Мне как-то странно, что можно приступить к работе, не понимая, что и когда эти свойства делают. Тем более, что все они только на чтение и, как правило, не меняют своего значения в процессе работы.
Если вы пользуетесь IList, например, и не знаете, что означают ReadOnly/IsFixedSize, то о какой компетентности может идти речь?
Если вы открыто высказываете мнение об ошибках проектироващиков, но при этом не в курсе, как проктировалось осуждаемое вами и почему оно именно такое — то не оскоррбляться надо, когда вам рассказывают, как дело было и почему и зачем вышло так, как есть, а мотать на ус, испытывая чувство благодарности за то, что кто-то тратит время, рассказывая вам то, что вы ранее не знали. му должны были научить ещё в ВУЗетребуя перед каждой самостоятельной изыскательной или "научной" работой осветить первым делом то, что уже было сделано до ваших рассуждений и выдумок.
Теперь вспоминайте, что дедушка уже такой старенький, что мог читать ещё того Рихрера
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, MozgC, Вы писали:
_FR>Если вы пользуетесь IList, например, и не знаете, что означают ReadOnly/IsFixedSize, то о какой компетентности может идти речь?
Я лично не использую IList и никаких угрызений совести по поводу незнания его свойств не испытываю. Тем более что при ознакомлении с ним я вижу те же грабли, что и в IList<T>.
_FR>Если вы открыто высказываете мнение об ошибках проектироващиков, но при этом не в курсе, как проктировалось осуждаемое вами и почему оно именно такое — то не оскоррбляться надо, когда вам рассказывают, как дело было и почему и зачем вышло так, как есть, а мотать на ус, испытывая чувство благодарности за то, что кто-то тратит время, рассказывая вам то, что вы ранее не знали. му должны были научить ещё в ВУЗетребуя перед каждой самостоятельной изыскательной или "научной" работой осветить первым делом то, что уже было сделано до ваших рассуждений и выдумок.
Благодарю за потраченное время, но суть всей эпопеи заключена в выделенном. Извиняюсь, но никаких откровений в рассказе я не увидел. Все еще считаю что из старых ошибок получились новые. И вобщем-то все эти рассказы мое убеждение подтверждают.
_FR>Теперь вспоминайте, что дедушка уже такой старенький, что мог читать ещё того Рихрера
И прежде чем науськивать его, перечисляя "второе и третье издание" понять, что первым же делом, и к бабке не ходи, вас отошлют к первому.
Русское издание 2002-го года никак не могло содержать информацию об особенностях реализаций массивом дженериковых интерфейсов, как и о причинно следственных связях этих особенностей.
Если дедушка такой старенький, то наверняка он помнит, что дженерики стали доступны весной 2004-го в первой бете vs2005 и претерпевали множество изменений до релиза. Например, в одной из бетта версий (не помню конкретно которой) при кастинге массива в IList<T> получался полностью иммутабельный объект, т.е. через сеттер индексатора IList<T> изменить содержимое массива было нельзя. Однако в документации той же беты было упоминание о том, что не стоит в дальнейшем рассчитывать на такое поведение. Причин отказа от этого решения я не знаю.
Здравствуйте, adontz, Вы писали:
S>>Я тоже считаю что в интерфейсах коллекций бардак. Другое дело — я привык к нему. Предлагать ничего не буду, не готов прямо сейчас, да и бестолку это. Но уверен, что можно было сделать лучше.
A>Без множественного наследования — нельзя.
Для справки: в дотнете для интерфейсов поддерживается множественное наследование. Ну, а интерфейс нужно было проектировать примерно так:
interface IList<T>
{
члены для чтения данных
}
interface IMutableList<T> : IList<T>
{
члены для изменения данных
}
Заметь, даже множественное наследование не понадобилось. Хотя можно было и его заюзать.
ЗЫ
Ром, странно от тебя слышать такое.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
A>>А я постоянно. Никогда не объявляю переменную конкретного типа за исключением случаев, когда иначе нельзя. Всегда использую самый базовый тип, какой только возможно. VD>Зачем?
Коллекция не всегда создаётся и заполняется в рамках одного метода, так что будьте знакомы — http://en.wikipedia.org/wiki/Interface_segregation_principle
VD>>>Когда коллекция заполняется, то обычно работа идет с конкретными типами. A>>Прямо противоположный опыт. В общем ты сам испугался что интерфейсов много и решил оставить только readonly. Совсем не интересный вариант. VD>Может стоит подумать над тем что и зачем ты делаешь?
Зачем я не сообщаю всем подряд тип класса конкретной реализации? Мне что, действительно придётся это объяснять?
Вообще-то конечно жить лучше своими мозгами, но все же ты бы прежде чем давать ссылку почитал бы ее. Это статья как раз о том почему в IList не должно быть Insert().
A>Зачем я не сообщаю всем подряд тип класса конкретной реализации? Мне что, действительно придётся это объяснять?
Зачем кому-то рассказывать о внутренней реализации?
ЗЫ
Есть один отличный принцип который я почерпнул из ФП. Если речь идет об обрабокте данных, то лучше стараться всегда делать ее так чтобы не изменять исходных данных. А к императиву прибегать только когда это оправдано соображениями производительности или иными весомыми соображениями. Тогда весь код по работе с коллекциями резко уходит в глубь методов, а на ружу начинают торчать списки (в немерле list[T]) и массивы (копии данных). При этом вопросов с абстрагированием или связанностью не возникает в принципе. Мы ведь всегда работаем с "отключенными" данными (копиями).
Так что если я вижу в коде передачу изменяемой коллекции (даже интерфейса) в другой метод, то это сразу же меня настораживает.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: int[].Add
От:
Аноним
Дата:
25.11.10 06:48
Оценка:
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
А>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн?
A>А какова альтернатива?
чтобы у меня были доступны методы которые я могу всегда использовать
Re[4]: int[].Add
От:
Аноним
Дата:
25.11.10 06:58
Оценка:
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
A>>>А какова альтернатива? А>>чтобы у меня были доступны методы которые я могу всегда использовать
A>И как вы предлагаете это реализовать? IList<> может быть поиницилизирован очень далеко, вообще в другом модуле. С какой стати компилятору запрещать вам вызывать метод?
как реализовать это вопрос другой. я говорю про то, что если у вас есть кнопка на телефоне Позвонить, то она должна звонить, а не говорить мне "я не могу это сделать, т.к. кнопку воткнули для совместимости с общим модулем управления клавиатурой"
Re[6]: int[].Add
От:
Аноним
Дата:
25.11.10 07:13
Оценка:
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, Аноним, Вы писали:
A>>>И как вы предлагаете это реализовать? IList<> может быть поиницилизирован очень далеко, вообще в другом модуле. С какой стати компилятору запрещать вам вызывать метод? А>>как реализовать это вопрос другой.
A>Это основной вопрос. Если вы не можете предложить ничего лучше, то не ругайте то, что есть.
основной вопрос: зачем показывать то, что мне недоступно для использования?
предложение: чтобы мне было доступно, что я могу использовать. зачем мне бутафория
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, Аноним, Вы писали:
А>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн?
Q>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern».
Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
А>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн?
А какая разница — всегда или нет? Вы же вызываете Add у интерфейса и с точки зрения интерфейса вызов Add далеко не "всегда будет кидать эксепшн"
А вот с точки зрения массива у вас метода Add нет.
Если так топорно, "c т.з. пользователя", как вы демонстрируете, рассуждать, то зачем вообще могут быть (имеют ли право на существование?) методы, которые, в зависимости от внутреннего состояния объекта, могут вести себя по разному (например, при некотором состоянии всегда "кидать")? (Заметьте, что нарушением LSP тут и не пахнет, ибо говорим мы не о наследовании, а о реализации интерфейсов.)
Развивая далее: методов a-la
override void M1() {
throw new NotSupportedException();
}
override void M2() {
throw new NotImplementedException();
}
быть так же не должно, как вам кажется? Или какие-то оговорки на этот счёт "для пользователя" могут иметь место?
Если вы неквалифицированный "пользователь", то никакого права диктовать, _как_ должно выглядеть то, что сделано [допустим] специалистом, у вас нет. Главное, что бы вы могли решить все заявленные задачи с помощью сделанного. Квалифицированный же "пользователь" не может быть квалифицированным без знания аспектов использования предмета критики. Вы же увидели один частный пример и на основании его делаете вывод о чьих-то ошибках. Вы не квалифицированный пользователь и ваше мнение не может быть интересно.
Что бы заинтересовать, рассуждайте шире. Рассмотрите всевозможные сценарии использования коллекций. Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны. Массивов и ReadOnlyCollection<> часто достаточно. ReadOnlyCollection2<> (без реализации IList/IList<>), ReadOnlySet<>, ReadOnlyDictionary<> и ковариантные классы readonly-коллекций для нового фреймворка могут покрыть все задачи. Заметье, речь тут не об интерфейсах, а о классах, которые вы можете написать самостоятельно и использовать, не имея никаких проблем с тем, что где-то видно больше, чем хотелось бы. Если у вас есть какая-то задача, которую нельзя было бы решить предложенным мною способом, было бы интересно взглянуть. Но подумайте, пожалуйста, хорошенько.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, samius, Вы писали:
А>>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн? Q>>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern». S>Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
В этом суть паттерна и заключена, что на все подобные кейсы "есть рецепт". Подробнее ознакомиться можно здесь.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: int[].Add
От:
Аноним
Дата:
25.11.10 08:10
Оценка:
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Аноним, Вы писали:
[skipped]
много казуистики.
конкретные вещи:
есть розетки на 360, а есть на 220В. Розетка в данном случае — это интерфейс.
Я не могу вставить вилку 220 в 360.
Считай, что метод Add это вставки вилки в розетку
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, samius, Вы писали:
А>>>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн? Q>>>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern». S>>Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
_FR>В этом суть паттерна и заключена, что на все подобные кейсы "есть рецепт". Подробнее ознакомиться можно здесь.
Хорошо, как понять можно ли использовать индексатор списка на запись?
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, samius, Вы писали:
A>>>Без множественного наследования — нельзя. S>>И для чего оно тут?
A>Потому что иначе получишь комбинаторный рост количества реализаций от количества интерфейсов. enumerable/readonly/resizable — это три разных признака. И тебе надо сделать какую-то системную реализаую для колелкции размер которой менять нельзя, но можно менять элементы.
Из них массив является лишь enumerable. В чем проблема? Где взрыв? Где множественное наследование?
A>Без множественного наследования будешь выписывать все варианты копипейстом. Можно привести фундаментальный и более просотой пример — System.Stream vs. istream/ostream.
Напомню, мы говорим о коллекциях и их интерфейсах.
Это ReadOnly класса Array. В примере автора используется явная реализация интерфейса ICollection<T>, которая возвращает true.
S>А потом, если arr.IsReadonly все-таки true, то его наверно изменять нельзя через индексатор?
Через индексатор можно (для него ReadOnly — false), через ICollection — нет (для него ReadOnly — true).
QL>Это ReadOnly класса Array. В примере автора используется явная реализация интерфейса ICollection<T>, которая возвращает true.
Пусть так
S>>А потом, если arr.IsReadonly все-таки true, то его наверно изменять нельзя через индексатор?
QL>Через индексатор можно (для него ReadOnly — false), через ICollection — нет (для него ReadOnly — true).
Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
Здравствуйте, samius, Вы писали:
A>>Потому что иначе получишь комбинаторный рост количества реализаций от количества интерфейсов. enumerable/readonly/resizable — это три разных признака. И тебе надо сделать какую-то системную реализаую для колелкции размер которой менять нельзя, но можно менять элементы. S>Из них массив является лишь enumerable. В чем проблема? Где взрыв? Где множественное наследование?
Массив в таком случае должен реализовывать два интерфейса — для перечисления и для изменения значения элемента и не должен реализовывать интерфейс для смены размера. Как несложно посчитать всего существует 3 + 3*2 + 1 = 10 разных комбинаций. То есть если уж ввёл интерфейсы, то будь добр реализовать 10 разных стандартных коллекций на все случаи жизни.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, samius, Вы писали:
A>>>Потому что иначе получишь комбинаторный рост количества реализаций от количества интерфейсов. enumerable/readonly/resizable — это три разных признака. И тебе надо сделать какую-то системную реализаую для колелкции размер которой менять нельзя, но можно менять элементы. S>>Из них массив является лишь enumerable. В чем проблема? Где взрыв? Где множественное наследование?
A>Массив в таком случае должен реализовывать два интерфейса — для перечисления и для изменения значения элемента и не должен реализовывать интерфейс для смены размера. Как несложно посчитать всего существует 3 + 3*2 + 1 = 10 разных комбинаций. То есть если уж ввёл интерфейсы, то будь добр реализовать 10 разных стандартных коллекций на все случаи жизни.
Я бы удовлетворился стандартными контейнерами. Мне не нравится что интерфейсы не fine-grained.
Здравствуйте, samius, Вы писали:
S>Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
S>Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
Явная реализация интерфейса. Здесь А — аналог ICollection<T>, B — аналог Array
interface A
{
bool IsReadonly { get; }
}
class B : A
{
public bool IsReadonly
{
get { return false; }
}
bool A.IsReadonly
{
get { return true; }
}
}
Здравствуйте, samius, Вы писали:
S>Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
Может, вопрос терминологии, но я не пойму, как можно изменять коллекцию через индексатор. Add меняет коллекцию; через индексатор же можно изменить элемент коллекции. Свойство «read only» коллекции не распространяется на её элементы.
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: int[].Add
От:
Аноним
Дата:
25.11.10 08:35
Оценка:
Здравствуйте, LF, Вы писали:
А>>конкретные вещи: А>>есть розетки на 360, а есть на 220В. Розетка в данном случае — это интерфейс. А>>Я не могу вставить вилку 220 в 360. А>>Считай, что метод Add это вставки вилки в розетку LF>Приведение массива к интерфейсу это использование переходника для вилки. С переходником вставить сможешь.
Здравствуйте, QrystaL, Вы писали:
S>>Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
QL>Явная реализация интерфейса. Здесь А — аналог ICollection<T>, B — аналог Array
Есть IList<T>. Как узнать, можно ли изменить элемент через индексатор без исключений и даункастов?
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, samius, Вы писали:
A>>>Вообще-то, есть свойство IsFixedSize S>>У другого интерфейса. Я просил без даункаста
A>Акстись, у какого другого?
A>
A>[ComVisible(true)]
A>public interface IList : ICollection, IEnumerable
A>
Мой вопрос был о IList<T>. Между ними ничего общего.
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, samius, Вы писали:
S>>Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
Q>Может, вопрос терминологии, но я не пойму, как можно изменять коллекцию через индексатор. Add меняет коллекцию; через индексатор же можно изменить элемент коллекции. Свойство «read only» коллекции не распространяется на её элементы.
Мне вообще не понятно, к чему же таки относится это свойство.
var arr = new [] {1, 2};
((IList<int>)arr).IsReadOnly.Dump(); // True
((IList)arr).IsReadOnly.Dump(); // False
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, samius, Вы писали:
S>>Я бы удовлетворился стандартными контейнерами. Мне не нравится что интерфейсы не fine-grained.
A>Смысла в это всё равно нет, потому что я лично сам встречался со случаями когда коллекция ReadOnly/FixedSize иногда. Интерфейсами такое не обозначить.
Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
Здравствуйте, samius, Вы писали:
Q>>Может, вопрос терминологии, но я не пойму, как можно изменять коллекцию через индексатор. Add меняет коллекцию; через индексатор же можно изменить элемент коллекции. Свойство «read only» коллекции не распространяется на её элементы.
S>Мне вообще не понятно, к чему же таки относится это свойство. S>
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, samius, Вы писали:
Q>>>Может, вопрос терминологии, но я не пойму, как можно изменять коллекцию через индексатор. Add меняет коллекцию; через индексатор же можно изменить элемент коллекции. Свойство «read only» коллекции не распространяется на её элементы.
S>>Мне вообще не понятно, к чему же таки относится это свойство. S>>
Q>Я так понял (в код не заглядывал), имеет место Explicit Interface Implementation.
Это для меня постижимо. Логика такого решения — нет.
Q>Всё-таки, при чём здесь индексатор?
Я не знаю причем, но по какому свойству тогда ориентироваться, можно ли изменять элементы коллекции? Или это дыра в Optional Features Pattern?
Здравствуйте, samius, Вы писали:
Q>>Всё-таки, при чём здесь индексатор? S>Я не знаю причем, но по какому свойству тогда ориентироваться, можно ли изменять элементы коллекции? Или это дыра в Optional Features Pattern?
По свойству «read only» элемента коллекции (если такое свойство есть). К Optional Features Pattern'у, его альтернативам и вообще коллекциям/интерфейсам это не имеет совсем никакого отношения. Это вопрос глубокой/неглубокой иммутабельности, он ортогонален обсуждаемой теме.
Здравствуйте, samius, Вы писали:
А>>>>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн? Q>>>>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern». S>>>Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
_FR>>В этом суть паттерна и заключена, что на все подобные кейсы "есть рецепт". Подробнее ознакомиться можно здесь.
S>Хорошо, как понять можно ли использовать индексатор списка на запись?
Я, признаться, удивлён: говорить о том, что коллекции сделаны не лучшим образом и не знать базовых интерфейсов коллекций
Единственная коллекция с таким свойством — массив, и специально для него было сделано IList.IsFixedSize Property. Об этом, если не ошибаюсь, даже Рихтер писал. Классику всё-таки по диагонали читать не следует, что бы не задавать потом подобных вопросов.
Help will always be given at Hogwarts to those who ask for it.
S>dynamic ad = arr;
S>bool r = ad.IsReadOnly;
S>r.Dump(); // False
S>
With the new dynamic keyword in C# 4.0, a method call on a dynamic object is resolved at runtime. Is is therefore impossible to access the explicitly implemented member on a dynamic object.
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, samius, Вы писали:
Q>>>Всё-таки, при чём здесь индексатор? S>>Я не знаю причем, но по какому свойству тогда ориентироваться, можно ли изменять элементы коллекции? Или это дыра в Optional Features Pattern?
Q>По свойству «read only» элемента коллекции (если такое свойство есть). К Optional Features Pattern'у, его альтернативам и вообще коллекциям/интерфейсам это не имеет совсем никакого отношения. Это вопрос глубокой/неглубокой иммутабельности, он ортогонален обсуждаемой теме.
Причем здесь свойства элемента коллекции?
Есть метод
void SetValueIfCan(IList<T> list, int index, T value)
{
// как узнать, можно ли вызывать сеттер?
list[0] = value;
}
Здравствуйте, Аноним, Вы писали:
А>>>конкретные вещи: А>>>есть розетки на 360, а есть на 220В. Розетка в данном случае — это интерфейс. А>>>Я не могу вставить вилку 220 в 360. А>>>Считай, что метод Add это вставки вилки в розетку
_FR>>А кто вам _обещал_ какую-то конкретную розетку или вилку? Чем одна розетка\вилка лучше другой? Ничем, они равноправны. А переходники у любого _квалифицированного_ путешественника должны быть в наличии. Из приведённого вами примера виднен лишь недостаток квалификации
_FR>>Продолжайте, весилите публику в том же духе.
А>по сути ответа на конкретный пример не услышал — следовательно, сказать нечего
Я тоже не услышал выше ответов по сути. Однако вы что-то всё-таки в ответ, не по сути, но сказали. Следовательно, ваш вывод о том, что сказать нечего мне — ошибочен. Качайтесь :о)
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, samius, Вы писали:
S>А потом, если arr.IsReadonly все-таки true, то его наверно изменять нельзя через индексатор?
Ну ёлки-палки. Неужели так сложно погуглить и почитать о том, что означают свойства базовых интерфейсов коллекций И как можно о чём-то говорить, не имея таких примитивных знаний?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
S>>Хорошо, как понять можно ли использовать индексатор списка на запись?
_FR>Я, признаться, удивлён: говорить о том, что коллекции сделаны не лучшим образом и не знать базовых интерфейсов коллекций
_FR>Единственная коллекция с таким свойством — массив, и специально для него было сделано IList.IsFixedSize Property. Об этом, если не ошибаюсь, даже Рихтер писал. Классику всё-таки по диагонали читать не следует, что бы не задавать потом подобных вопросов.
FRED, я зол!
Ты даже не второй, кто мне предлагает для ответа на вопрос, можно ли по IList<T> узнать о возможности использования сеттера индексатора без даункаста, воспользвоаться IList-ом.
Благодарю за "внимательность".
Здравствуйте, samius, Вы писали:
S>>>Это как? свойство IsReadOnly определено у ICollection<T>. Как оно может вызываться по-разному в зависимости от того, хочу ли я узнать можно ли Add, или можно ли изменять через индексатор?
A>>Вообще-то, есть свойство IsFixedSize S>У другого интерфейса. Я просил без даункаста
Нет, вы действительно Рихтера не читали? Хоть одну коллекцию кроме массива можете привести в качестве примера, в которой был бы нужен IsFixedSize? Именно поэтому, потому что было сложно в большенстве голов уложить как IsFixedSize так и IsReadOnly, а так же из-за того, что кроме массива это более нигде было не нужно, в generic-коллекциях от этого отказались, оставив лишь IsReadOnly. Архитекторы блин, недоученные.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, samius, Вы писали:
S>>А потом, если arr.IsReadonly все-таки true, то его наверно изменять нельзя через индексатор?
_FR>Ну ёлки-палки. Неужели так сложно погуглить и почитать о том, что означают свойства базовых интерфейсов коллекций И как можно о чём-то говорить, не имея таких примитивных знаний?
Здравствуйте, samius, Вы писали:
S>>>Хорошо, как понять можно ли использовать индексатор списка на запись? _FR>>Я, признаться, удивлён: говорить о том, что коллекции сделаны не лучшим образом и не знать базовых интерфейсов коллекций
_FR>>Единственная коллекция с таким свойством — массив, и специально для него было сделано IList.IsFixedSize Property. Об этом, если не ошибаюсь, даже Рихтер писал. Классику всё-таки по диагонали читать не следует, что бы не задавать потом подобных вопросов.
S>FRED, я зол! S>Ты даже не второй, кто мне предлагает для ответа на вопрос, можно ли по IList<T> узнать о возможности использования сеттера индексатора без даункаста, воспользвоаться IList-ом. S>Благодарю за "внимательность".
Ну если ответ небыл известен, что плохого в том, что ответ получен несколько раз А если всё-таки был известен: почему не указать этого в сразу — мы же не подсекаем тут друг друга, подлавливая на ошибках и пытаясь выяснить, у кого больше, а пытаемся узнать, как лучше. Вот если ответ был известен, надо было бы так и написать, что IsFixedSize нет и без него никак. Ну а если забыли — ну и что что несколько раз напомнили?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, samius, Вы писали:
Q>>>Может, вопрос терминологии, но я не пойму, как можно изменять коллекцию через индексатор. Add меняет коллекцию; через индексатор же можно изменить элемент коллекции. Свойство «read only» коллекции не распространяется на её элементы.
Да, вопрос терминологии, говорили о разных вещах. Точнее, я изначально понял всё превратно, зачем-то добавил лишний уровень косвенности, евпочя.
S>Есть метод S>
S>void SetValueIfCan(IList<T> list, int index, T value)
S>{
S> // как узнать, можно ли вызывать сеттер?
S> list[0] = value;
S>}
S>
Здравствуйте, samius, Вы писали:
S>>>А потом, если arr.IsReadonly все-таки true, то его наверно изменять нельзя через индексатор? _FR>>Ну ёлки-палки. Неужели так сложно погуглить и почитать о том, что означают свойства базовых интерфейсов коллекций И как можно о чём-то говорить, не имея таких примитивных знаний?
S>http://msdn.microsoft.com/en-us/library/bb346454.aspx S>
S>A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created.
S>Погуглил. После этого ты будешь утверждать что изменение элементов массива запрещено?
После этого я скажу, что где-то читал, что IsFixedSize (именно то, что вам сейчас хочется) оказался не нужен в базовых интерфейсах и поддержку его в базовом АПИ сочли излишней. Единственно общее место (не беря в расчёт очень редкую специфику), где IsFixedSize необходим — массив. И держать IsFizedSize в очень общем интерфейсе, заставляя каждую пользовательскую коллекцию его реализовывать, не нужно. В generic оставили один признак — IsReadOnly, покрым этим 99% случаев. Поэтому, если вам это важно, обработайте этот кейс, проверив объект на IList или на массив. Последнее возможно без приведений типов.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, samius, Вы писали:
S>>>>А потом, если arr.IsReadonly все-таки true, то его наверно изменять нельзя через индексатор? _FR>>>Ну ёлки-палки. Неужели так сложно погуглить и почитать о том, что означают свойства базовых интерфейсов коллекций И как можно о чём-то говорить, не имея таких примитивных знаний?
S>>http://msdn.microsoft.com/en-us/library/bb346454.aspx S>>
S>>A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created.
S>>Погуглил. После этого ты будешь утверждать что изменение элементов массива запрещено?
_FR>После этого я скажу, что где-то читал, что IsFixedSize (именно то, что вам сейчас хочется) оказался не нужен в базовых интерфейсах и поддержку его в базовом АПИ сочли излишней. Единственно общее место (не беря в расчёт очень редкую специфику), где IsFixedSize необходим — массив. И держать IsFizedSize в очень общем интерфейсе, заставляя каждую пользовательскую коллекцию его реализовывать, не нужно. В generic оставили один признак — IsReadOnly, покрым этим 99% случаев. Поэтому, если вам это важно, обработайте этот кейс, проверив объект на IList или на массив. Последнее возможно без приведений типов.
В том и предыдущем сообщении я больше интересуюсь возможностью изменения элементов массива через индексатор. Что-то мне подсказывает, что IsFixedSize тут не поможет. IsReadOnly я использовать побоюсь, т.к. даже у одной и той же сущности он возвращает разные результаты. Допустим, сейчас я разберусь в этой ситуации, а что делать когда через пол-года увижу очень неочевидный код у себя? Опять разбираться в этом вопросе? Предпочту табу на это свойство.
Единственный разумный выход — тестировать на is T[].
Кстати, от IList<T> к IList без приведения типов не перейти.
Здравствуйте, samius, Вы писали:
А>>>>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн? Q>>>>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern». S>>>Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
_FR>>В этом суть паттерна и заключена, что на все подобные кейсы "есть рецепт". Подробнее ознакомиться можно здесь.
S>Хорошо, как понять можно ли использовать индексатор списка на запись?
Пытаясь вернуться на продуктивный путь: когда-нить это было нужно? Причем, в отрыве от массива. Никакой разумной структуры данных кроме массива с таким свойством на ум не приходит.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, samius, Вы писали:
А>>>>>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн? Q>>>>>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern». S>>>>Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
_FR>>>В этом суть паттерна и заключена, что на все подобные кейсы "есть рецепт". Подробнее ознакомиться можно здесь.
S>>Хорошо, как понять можно ли использовать индексатор списка на запись?
_FR>Пытаясь вернуться на продуктивный путь: когда-нить это было нужно? Причем, в отрыве от массива. Никакой разумной структуры данных кроме массива с таким свойством на ум не приходит.
Реально — нет.
Я лишь докапываюсь к выделенному. Использовать подобные вещи без глубокого изучения и понимания можно. Но считать это верным и красивым решением я отказываюсь.
Считаю что в программировании есть куда более интересные и полезные вещи, чем запоминание _таких_ тонкостей.
Здравствуйте, samius, Вы писали:
A>>Смысла в это всё равно нет, потому что я лично сам встречался со случаями когда коллекция ReadOnly/FixedSize иногда. Интерфейсами такое не обозначить. S>Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
Проще свойствами. И если они как-то нелогично работают у массива это не значит что путь в целом неправильный.
Здравствуйте, samius, Вы писали:
А>>>>>>>кто мне объяснит зачем мне доступен метод Add, который всегда будет кидать эксепшн? Q>>>>>>«Framework Design Guidelines», глава «9.7 Optional Feature Pattern». S>>>>>Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
_FR>>>>В этом суть паттерна и заключена, что на все подобные кейсы "есть рецепт". Подробнее ознакомиться можно здесь.
S>>>Хорошо, как понять можно ли использовать индексатор списка на запись?
_FR>>Пытаясь вернуться на продуктивный путь: когда-нить это было нужно? Причем, в отрыве от массива. Никакой разумной структуры данных кроме массива с таким свойством на ум не приходит. S>Реально — нет.
Тогда это разговор примерно такого же уровня, как "Мне нужен класс Form у которого небыло бы свойства Caption, поскольку он мне не нужен, а раз такого нет — архитектура дотнета отстой".
S>Я лишь докапываюсь к выделенному. Использовать подобные вещи без глубокого изучения и понимания можно. Но считать это верным и красивым решением я отказываюсь.
Как раз таки generic-коллекциях всё упрощено: вам же с одной стороны хочется "богатства" (узнать то, узнать другое) с другой вы не хотите "глубоко изучать" Одно ваше желание противоречит другому.
Касательно выделенного: я рассчитывал, что вы знаете о том, какие свойства и для чего имеются в коллекциях, а оказалось, что это не так. Так вот в дженерик-коллекциях есть разделение только на риддонли и неридлонли. В не-дженерик есть ещё и IsFixedSize, который просто не нужен в подавляющем большинстве случаев. Но нигде, например, нет CanAdd/CanRemove. А почему бы и их не вынести так же как отдельные интерфейсы? Вот здесь уже пора почувствовать "комбинаторность". А требование такого свойства от IList<> или от IList ничем не лучше любого другого надуманного ("можно ли использовать индексатор списка на запись") свойства.
S>Считаю что в программировании есть куда более интересные и полезные вещи, чем запоминание _таких_ тонкостей.
Каких "таких" мне не ясно, но если это ваше оправдание незнанию ннекоторых вещей, то мне всё равно.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, samius, Вы писали:
S>>>Погуглил. После этого ты будешь утверждать что изменение элементов массива запрещено? _FR>>После этого я скажу, что где-то читал, что IsFixedSize (именно то, что вам сейчас хочется) оказался не нужен в базовых интерфейсах и поддержку его в базовом АПИ сочли излишней. Единственно общее место (не беря в расчёт очень редкую специфику), где IsFixedSize необходим — массив. И держать IsFizedSize в очень общем интерфейсе, заставляя каждую пользовательскую коллекцию его реализовывать, не нужно. В generic оставили один признак — IsReadOnly, покрым этим 99% случаев. Поэтому, если вам это важно, обработайте этот кейс, проверив объект на IList или на массив. Последнее возможно без приведений типов. S>В том и предыдущем сообщении я больше интересуюсь возможностью изменения элементов массива через индексатор. Что-то мне подсказывает, что IsFixedSize тут не поможет.
"Что-то" ошибается. Дело в том, что IList.IsReadOnly и ICollection<>.IsReadOnly — несколько разные IsReadOnly. И это совсем не сложно. Если вы этого раньше не знали, не нужно оправдывать незнание тем, что это сложно и не нужно, а так же опасно.
S>IsReadOnly я использовать побоюсь, т.к. даже у одной и той же сущности он возвращает разные результаты.
Нет. Каждый конкретный раз возвращается вполне определённое значение. Если вы запутались в трёх соснах, то я в этом не виноват.
S>Допустим, сейчас я разберусь в этой ситуации, а что делать когда через пол-года увижу очень неочевидный код у себя? Опять разбираться в этом вопросе? Предпочту табу на это свойство.
Я, например, делаю совсем по-другому.
S>Единственный разумный выход — тестировать на is T[].
Говорить о каком-то "разумном выходе" в более чем гипотетическом примере я нахожу странным.
S>Кстати, от IList<T> к IList без приведения типов не перейти.
Спасибо, не знал.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, samius, Вы писали:
A>>>>Смысла в это всё равно нет, потому что я лично сам встречался со случаями когда коллекция ReadOnly/FixedSize иногда. Интерфейсами такое не обозначить. S>>>Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
A>>Проще свойствами. И если они как-то нелогично работают у массива это не значит что путь в целом неправильный. S>Мне сложно назвать правильным путь, в рамках которого одна из наиболее часто используемых сущностей ведет себя нелогично, либо логика ее работы не очевидна, а на счет остальных нельзя сказать, можно ли изменять их элементы.
Вот это — "пять", как говорится. То есть "неочевидная логика" в вашей логике "нелогична" И всего навсего из-за пропущенных/забытых глав из Рихтера. Потрясающая логика — рассуждать о логичности того, с чем впервые столкнулся. ИМХО, рассуждая таким путём _очень_ сложно не ошибиться.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>>>Пытаясь вернуться на продуктивный путь: когда-нить это было нужно? Причем, в отрыве от массива. Никакой разумной структуры данных кроме массива с таким свойством на ум не приходит. S>>Реально — нет.
_FR>Тогда это разговор примерно такого же уровня, как "Мне нужен класс Form у которого небыло бы свойства Caption, поскольку он мне не нужен, а раз такого нет — архитектура дотнета отстой".
Он и есть такого уровня. Я что, не могу выразить свое несогласие с решением? Я ведь не предлагаю переписать дотнет или бойкотировать его?
S>>Я лишь докапываюсь к выделенному. Использовать подобные вещи без глубокого изучения и понимания можно. Но считать это верным и красивым решением я отказываюсь.
_FR>Как раз таки generic-коллекциях всё упрощено: вам же с одной стороны хочется "богатства" (узнать то, узнать другое) с другой вы не хотите "глубоко изучать" Одно ваше желание противоречит другому.
Богатства там нет.
_FR>Касательно выделенного: я рассчитывал, что вы знаете о том, какие свойства и для чего имеются в коллекциях, а оказалось, что это не так. Так вот в дженерик-коллекциях есть разделение только на риддонли и неридлонли. В не-дженерик есть ещё и IsFixedSize, который просто не нужен в подавляющем большинстве случаев. Но нигде, например, нет CanAdd/CanRemove. А почему бы и их не вынести так же как отдельные интерфейсы? Вот здесь уже пора почувствовать "комбинаторность". А требование такого свойства от IList<> или от IList ничем не лучше любого другого надуманного ("можно ли использовать индексатор списка на запись") свойства.
Я не требовал свойства.
S>>Считаю что в программировании есть куда более интересные и полезные вещи, чем запоминание _таких_ тонкостей.
_FR>Каких "таких" мне не ясно, но если это ваше оправдание незнанию ннекоторых вещей, то мне всё равно.
_таких_ — это запоминание того, что IList.IsReadOnly возвращает одно, а IList<T>.IsReadOnly — другое значение; какое из них нужно использовать для того что бы что-то узнать о коллекции, и т.п.
Забивать этим голову я не собираюсь, кому бы ни было все равно.
Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, samius, Вы писали:
>>Есть рецепт, как можно понять, можно ли вызывать метод IList<T>.Add без получения исключения и даункастинга?
I>Есть.
видимо if(list.GetType().IsArray) ?
Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, samius, Вы писали:
I>>>Есть. S>>видимо if(list.GetType().IsArray) ?
I>Предположим, да. Что дальше ?
Ничего. Я получил ответ на вопрос, который терзал меня. Всем спасибо.
Здравствуйте, _FRED_, Вы писали:
_FR>Что бы заинтересовать, рассуждайте шире. Рассмотрите всевозможные сценарии использования коллекций. Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны. Массивов и ReadOnlyCollection<> часто достаточно. ReadOnlyCollection2<> (без реализации IList/IList<>), ReadOnlySet<>, ReadOnlyDictionary<> и ковариантные классы readonly-коллекций для нового фреймворка могут покрыть все задачи. Заметье, речь тут не об интерфейсах, а о классах, которые вы можете написать самостоятельно и использовать, не имея никаких проблем с тем, что где-то видно больше, чем хотелось бы. Если у вас есть какая-то задача, которую нельзя было бы решить предложенным мною способом, было бы интересно взглянуть. Но подумайте, пожалуйста, хорошенько.
Т.е. если дистилировать весь твой пост — корявый дизайн массивов в дотнете. Так ?
Здравствуйте, Ikemefula, Вы писали:
_FR>>Что бы заинтересовать, рассуждайте шире. Рассмотрите всевозможные сценарии использования коллекций. Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны. Массивов и ReadOnlyCollection<> часто достаточно. ReadOnlyCollection2<> (без реализации IList/IList<>), ReadOnlySet<>, ReadOnlyDictionary<> и ковариантные классы readonly-коллекций для нового фреймворка могут покрыть все задачи. Заметье, речь тут не об интерфейсах, а о классах, которые вы можете написать самостоятельно и использовать, не имея никаких проблем с тем, что где-то видно больше, чем хотелось бы. Если у вас есть какая-то задача, которую нельзя было бы решить предложенным мною способом, было бы интересно взглянуть. Но подумайте, пожалуйста, хорошенько.
I>Т.е. если дистилировать весь твой пост — корявый дизайн массивов в дотнете. Так ?
Нет.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, samius, Вы писали:
_FR>>Вот это — "пять", как говорится. То есть "неочевидная логика" в вашей логике "нелогична" И всего навсего из-за пропущенных/забытых глав из Рихтера. Потрясающая логика — рассуждать о логичности того, с чем впервые столкнулся. ИМХО, рассуждая таким путём _очень_ сложно не ошибиться.
S>Можно таки ссылку на главу у Рихтера, проливающую свет на данный вопрос?
Вечером посмотрю, сейчас нет под рукой.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, Ikemefula, Вы писали:
_FR>>>Что бы заинтересовать, рассуждайте шире. Рассмотрите всевозможные сценарии использования коллекций. Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны. Массивов и ReadOnlyCollection<> часто достаточно. ReadOnlyCollection2<> (без реализации IList/IList<>), ReadOnlySet<>, ReadOnlyDictionary<> и ковариантные классы readonly-коллекций для нового фреймворка могут покрыть все задачи. Заметье, речь тут не об интерфейсах, а о классах, которые вы можете написать самостоятельно и использовать, не имея никаких проблем с тем, что где-то видно больше, чем хотелось бы. Если у вас есть какая-то задача, которую нельзя было бы решить предложенным мною способом, было бы интересно взглянуть. Но подумайте, пожалуйста, хорошенько.
I>>Т.е. если дистилировать весь твой пост — корявый дизайн массивов в дотнете. Так ?
_FR>Нет.
А что значит " Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны."
Раз они не нужны, значит их и незачем было реализовывать, т.к. это сбивает с толку пользователей.
При чём здесь документация? Мы не её обсуждаем. Но и это я покажу ниже. Потому что не смотря на моё раздражённое и, уверен, раздражающее, поведение вы более чем корректны Большое спасибо Просто очень не люблю, когда без знания дела начинают условия свои диктовать.
Напоминаю, о чём шла речь:
Что-то мне подсказывает, что IsFixedSize тут не поможет.
Так вот, логика старых интерфейсов коллекций была проста: всё, что не IList, всё readonly. А IList имеет два признака: IsFixedSize, показывающий, можно ли добавлять/удалять элементы и IsReadOnly, показывающий можно ли изменять элементы. Различия хорошо видны для массивов: для них IsFixedSize = true, а IsReadOnly = false. Это однозначно говорит о том, что мы не может добавлять/удалять элементы, но изменять сожержимое имеем право. Поэтому
Remarks
A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created.
совершенно верно: если IsReadOnly = true, нельзя добавлять/удалять/изменять, а в противном случае изменять можно (ведь другого не сказано), а по поводу добавления/удаления сказано в описании IsFixedSize.
В generic-коллекциях всё проще, там только IsReadOnly, который говорит о том [же], можно ли изменять элементы — но, так как нет уточняющего IsFixedSize, то логика его работы очень проста и для массива IList<>::IsReadOnly = true (в отличии от IList::IsReadOnly). То есть, по сути, вы не должны хоть как-то менять содержимое IList<> есть его IsReadOnly = true.
Другое дело, что реализация этого интерфейса массивом неожиданна: несмотря на IsReadOnly = true, изменять данные по индексатору она позволяет. Но, во-первых, это уже детали реализации и, во-вторых, это нигде [я не знаю где] не запрещено документацией.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Ikemefula, Вы писали:
_FR>>>>Что бы заинтересовать, рассуждайте шире. Рассмотрите всевозможные сценарии использования коллекций. Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны. Массивов и ReadOnlyCollection<> часто достаточно. ReadOnlyCollection2<> (без реализации IList/IList<>), ReadOnlySet<>, ReadOnlyDictionary<> и ковариантные классы readonly-коллекций для нового фреймворка могут покрыть все задачи. Заметье, речь тут не об интерфейсах, а о классах, которые вы можете написать самостоятельно и использовать, не имея никаких проблем с тем, что где-то видно больше, чем хотелось бы. Если у вас есть какая-то задача, которую нельзя было бы решить предложенным мною способом, было бы интересно взглянуть. Но подумайте, пожалуйста, хорошенько.
I>>>Т.е. если дистилировать весь твой пост — корявый дизайн массивов в дотнете. Так ?
_FR>>Нет.
I>А что значит " Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны." I>Раз они не нужны, значит их и незачем было реализовывать, т.к. это сбивает с толку пользователей.
И при чём же тут "корявый дизайн массивов в дотнете"
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
I>>>>Т.е. если дистилировать весь твой пост — корявый дизайн массивов в дотнете. Так ?
_FR>>>Нет.
I>>А что значит " Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны." I>>Раз они не нужны, значит их и незачем было реализовывать, т.к. это сбивает с толку пользователей.
_FR>И при чём же тут "корявый дизайн массивов в дотнете"
Интерфейсы не нужны а их всунули. или по твоему реализация ненужных интерфейсов вроде IList в Array это показатель качественного дизайна ?
Здравствуйте, Ikemefula, Вы писали:
I>>>>>Т.е. если дистилировать весь твой пост — корявый дизайн массивов в дотнете. Так ? _FR>>>>Нет. I>>>А что значит " Вы увидите, что интерфейсы для readonly-списков и коллекций попросту не нужны." I>>>Раз они не нужны, значит их и незачем было реализовывать, т.к. это сбивает с толку пользователей.
_FR>>И при чём же тут "корявый дизайн массивов в дотнете"
I>Интерфейсы не нужны а их всунули. или по твоему реализация ненужных интерфейсов вроде IList в Array это показатель качественного дизайна ?
Я не вижу, где и какие интерфейсы не нужны. IList/IList<> в массивах нужен. Излагайте мысли более чётко и более подробно — догадываться о т ом, что вы предполагаете я не желаю.
Help will always be given at Hogwarts to those who ask for it.
_FR>Так вот, логика старых интерфейсов коллекций была проста: всё, что не IList, всё readonly.
Hashtable не вписалась в эту логику.
_FR>А IList имеет два признака: IsFixedSize, показывающий, можно ли добавлять/удалять элементы и IsReadOnly, показывающий можно ли изменять элементы. Различия хорошо видны для массивов: для них IsFixedSize = true, а IsReadOnly = false. Это однозначно говорит о том, что мы не может добавлять/удалять элементы, но изменять сожержимое имеем право. Поэтому
_FR>
_FR>A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created.
_FR>совершенно верно: если IsReadOnly = true, нельзя добавлять/удалять/изменять, а в противном случае изменять можно (ведь другого не сказано), а по поводу добавления/удаления сказано в описании IsFixedSize.
Пока со всем согласен.
_FR>В generic-коллекциях всё проще, там только IsReadOnly, который говорит о том [же], можно ли изменять элементы — но, так как нет уточняющего IsFixedSize, то логика его работы очень проста и для массива IList<>::IsReadOnly = true (в отличии от IList::IsReadOnly). То есть, по сути, вы не должны хоть как-то менять содержимое IList<> есть его IsReadOnly = true.
Ну т.е. не должен — это на моей совести?
_FR>Другое дело, что реализация этого интерфейса массивом неожиданна: несмотря на IsReadOnly = true, изменять данные по индексатору она позволяет. Но, во-первых, это уже детали реализации и, во-вторых, это нигде [я не знаю где] не запрещено документацией.
Цитата выше утверждает что у read-only коллекций запрещено изменение элементов после создания коллекци без упоминания об исключении в виде массива и его разных реализациях казалось бы одного свойства.
Надежда на Рихтера. Я во 2м издании о 2м фреймворке не нашел ничего об этом, кроме того, что generic интерфейсы коллекций поддерживаются массивами динамически (и только одномерными с индексацией от 0-я).
Здравствуйте, _FRED_, Вы писали:
_FR>Я не вижу, где и какие интерфейсы не нужны. IList/IList<> в массивах нужен. Излагайте мысли более чётко и более подробно — догадываться о т ом, что вы предполагаете я не желаю.
То нужны то не нужны, " интерфейсы для readonly-списков и коллекций попросту не нужны"
Здравствуйте, samius, Вы писали:
_FR>>Так вот, логика старых интерфейсов коллекций была проста: всё, что не IList, всё readonly. S>Hashtable не вписалась в эту логику.
Это отдельный разговор — там есь IDictionary со всем, что нужно.
_FR>>В generic-коллекциях всё проще, там только IsReadOnly, который говорит о том [же], можно ли изменять элементы — но, так как нет уточняющего IsFixedSize, то логика его работы очень проста и для массива IList<>::IsReadOnly = true (в отличии от IList::IsReadOnly). То есть, по сути, вы не должны хоть как-то менять содержимое IList<> есть его IsReadOnly = true. S>Ну т.е. не должен — это на моей совести?
Что именно? Корректная реализация интерфейса? Конечно, как и при реализации любого интерфейса. От IsFixedSize отчасти из-за того и отказались, что в пользовательских коллекциях он, за исключением редчайших случаев, не нужен и равнозначен IsReadOnly.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Ikemefula, Вы писали:
_FR>>Я не вижу, где и какие интерфейсы не нужны. IList/IList<> в массивах нужен. Излагайте мысли более чётко и более подробно — догадываться о т ом, что вы предполагаете я не желаю. I>То нужны то не нужны, " интерфейсы для readonly-списков и коллекций попросту не нужны"
У вас какая-то сумятица в голове. Процитированное означает, что не нужны IReadOnlyCollection, IReadOnlyList и прочие ридонли-интерфейсы.
I>Для чего нужны IList/IList<> в массивах ?
Например, для того, что бы можно было бы написать обобщённый метод сортировки, принимающий IList/IList<>.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, samius, Вы писали:
_FR>>В generic-коллекциях всё проще, там только IsReadOnly, который говорит о том [же], можно ли изменять элементы — но, так как нет уточняющего IsFixedSize, то логика его работы очень проста и для массива IList<>::IsReadOnly = true (в отличии от IList::IsReadOnly). То есть, по сути, вы не должны хоть как-то менять содержимое IList<> есть его IsReadOnly = true. S>Ну т.е. не должен — это на моей совести?
А, вкурил Если хотите — можете менять на свой страх и риск. Все известные мне реализации коллекций ответят на это исключением. IList<> в описанном выше случае не сделает нечего, но это какая-то его специфическая особенность.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
I>>Для чего нужны IList/IList<> в массивах ?
_FR>Например, для того, что бы можно было бы написать обобщённый метод сортировки, принимающий IList/IList<>.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, samius, Вы писали:
_FR>>>В generic-коллекциях всё проще, там только IsReadOnly, который говорит о том [же], можно ли изменять элементы — но, так как нет уточняющего IsFixedSize, то логика его работы очень проста и для массива IList<>::IsReadOnly = true (в отличии от IList::IsReadOnly). То есть, по сути, вы не должны хоть как-то менять содержимое IList<> есть его IsReadOnly = true. S>>Ну т.е. не должен — это на моей совести?
_FR>А, вкурил Если хотите — можете менять на свой страх и риск. Все известные мне реализации коллекций ответят на это исключением. IList<> в описанном выше случае не сделает нечего, но это какая-то его специфическая особенность.
По поводу какой-то специфической особенности очень хотел съязвить. Не буду
Кстати, точно так же изменение массива не приводит к облому перечислителя массива. Но это-то как раз можно понять и предугадать.
Здравствуйте, samius, Вы писали:
_FR>>А, вкурил Если хотите — можете менять на свой страх и риск. Все известные мне реализации коллекций ответят на это исключением. IList<> в описанном выше случае не сделает нечего, но это какая-то его специфическая особенность. S>По поводу какой-то специфической особенности очень хотел съязвить. Не буду S>Кстати, точно так же изменение массива не приводит к облому перечислителя массива. Но это-то как раз можно понять и предугадать.
Прежде чем об этом рассуждать, наждо поинтересоваться у разработчиков, ибо это совершенно точно шаг в сторону от общепринятых договорённостей. И осмысленный ли это шаг или просто недосмотр, ИМХО, не очевидно.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, midcyber, Вы писали:
I>>Т.е. если дистилировать весь твой пост — корявый дизайн массивов в дотнете. Так ?
M>Ну вообще-то он действительно корявый
Ну что ты, разве может быть корявым дизайн, когда у класса могут быть две разных проперти но с одинаковым именем ?
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, samius, Вы писали:
S>>Кстати, точно так же изменение массива не приводит к облому перечислителя массива. Но это-то как раз можно понять и предугадать.
_FR>Прежде чем об этом рассуждать, наждо поинтересоваться у разработчиков, ибо это совершенно точно шаг в сторону от общепринятых договорённостей. И осмысленный ли это шаг или просто недосмотр, ИМХО, не очевидно.
Как раз все просто. Либо общепринятая договоренность, либо возможность обращаться к элементам массива через ссылки Swap(ref array[0], ref array[1]);
При изменении элементов массива через ссылки нет возможности соблюдать договоренность об обломе перечислителя. Так зачем делать разницу между изменением элемента массива через сеттер индексатора и напрямую? Ну а раз так, то и реализация сеттера индексатора IList<T> оказалась с нарушением договоренности. Хотя в последнем случае как раз была возможность ее соблюсти.
Здравствуйте, Ikemefula, Вы писали:
I>>>>>Для чего нужны IList/IList<> в массивах ? _FR>>>>Например, для того, что бы можно было бы написать обобщённый метод сортировки, принимающий IList/IList<>. I>>>Это какое то мелкое преимущество _FR>>Мне жаль, если ваша фантазия не позволяет вам отыскать других А они есть.
I>То есть примеров у тебя нет и ты решил удариться в словоблудие ?
Почему же? Если я сказал, что есть, значит есть. Доказать обратного вы не сможете же, так что словоблудием занимаетесь сами.
В качестве ещё одлного примера — из массива можно создать ReadOnlyCollection<>. Например, это позволит обойти странный феномен возможности изменения через индексер данных массива несмотря на IsReadOnly.
Так что дело по прежнему в работе вашей фантазии.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Ikemefula, Вы писали:
I>>>Это какое то мелкое преимущество
_FR>>Мне жаль, если ваша фантазия не позволяет вам отыскать других А они есть.
I>То есть примеров у тебя нет и ты решил удариться в словоблудие ?
Это обычный прием, чему ты удивляешься? Раз собеседник начинает переходить на личности, то аргументы закончились. Сам так регулярно делаю, иногда даже срабатывает.
Здравствуйте, Lloyd, Вы писали:
I>>То есть примеров у тебя нет и ты решил удариться в словоблудие ?
L>Это обычный прием, чему ты удивляешься? Раз собеседник начинает переходить на личности, то аргументы закончились. Сам так регулярно делаю, иногда даже срабатывает.
Мне нужно было таки выдавить из него ответ и я применил точно такой же приём
Здравствуйте, _FRED_, Вы писали:
I>>То есть примеров у тебя нет и ты решил удариться в словоблудие ?
_FR>Почему же? Если я сказал, что есть, значит есть. Доказать обратного вы не сможете же, так что словоблудием занимаетесь сами.
Вообще то каждый доказывает ровно то что говорит.
"Доказать обратного" — это конспироложество вроде "Бог есть или докажите обратное".
Ты сказал, что есть преимущества, на вопрос не ответил кроме как сортировкой
_FR>В качестве ещё одлного примера — из массива можно создать ReadOnlyCollection<>. Например, это позволит обойти странный феномен возможности изменения через индексер данных массива несмотря на IsReadOnly.
Можно подумать, если бы массив не реализовывал был интерфейсы, были бы какие то проблемы.
Всего лишь дизайн изменяется.
Смотри:
Предположим, массив не реализует никаких интерфейсво вроде ICollection или IList и тд.
Задача — из массива сделать ReadOnlyCollection<>.
Решение — создать конструктор ReadOnlyCollection который принимает Array.
Побочный эффект — IList и тд не является Array.
Устранение побочного эффекта — в интерфейсы вроде ICollection, IList добавить фунцыю ToArray() вместо дерьма вроде CopyTo()
Здравствуйте, Ikemefula, Вы писали:
I>Можно подумать, если бы массив не реализовывал был интерфейсы, были бы какие то проблемы. I>Всего лишь дизайн изменяется. I>Смотри: I>Предположим, массив не реализует никаких интерфейсво вроде ICollection или IList и тд. I>Задача — из массива сделать ReadOnlyCollection<>. I>Решение — создать конструктор ReadOnlyCollection который принимает Array. I>Побочный эффект — IList и тд не является Array. I>Устранение побочного эффекта — в интерфейсы вроде ICollection, IList добавить фунцыю ToArray() вместо дерьма вроде CopyTo()
Нет уж, сказали — покажите. Пока что я вижу возможность такого либо специализированной под массив, то есть отдельной, реализиции, либо копированием массива в список. И то и другое по сравнению с тем, что есть, выглядит намного хуже. Так как — сумеете ответить за свои слова и прести реализацию ReadOnlyCollection<>, поддерживающую как IList<> так и массив или не сумеете?
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, Ikemefula, Вы писали:
_FR>>Нет уж, сказали — покажите. Пока что я вижу возможность такого либо специализированной под массив, то есть отдельной, реализиции, либо копированием массива в список. И то и другое по сравнению с тем, что есть, выглядит намного хуже. Так как — сумеете ответить за свои слова и прести реализацию ReadOnlyCollection<>, поддерживающую как IList<> так и массив или не сумеете?
I>IList<> в ReadOnlyCollection есть зло !
I>В прынцыпе, в массиве IEnumerable можно оставить, шоб вообще всё было сильно
Спасибо, но ваш пример убедительно показывает вашу некомпетентность в обсуждаемом предмете, что и требовалось доказать. Копирование в конструкторе ReadOnlyCollection<> и прочие утверждения безумны.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Я, признаться, удивлён: говорить о том, что коллекции сделаны не лучшим образом и не знать базовых интерфейсов коллекций _FR>Единственная коллекция с таким свойством — массив, и специально для него было сделано IList.IsFixedSize Property. Об этом, если не ошибаюсь, даже Рихтер писал. Классику всё-таки по диагонали читать не следует, что бы не задавать потом подобных вопросов.
Можно показать, где Рихтер об этом писал, а то я и второе и третье издание читал, и такого не припомню. Если я прав, то может стоит удостовериться сначала, написано ли там такое, прежде чем оскорблять человека, говоря о его некомпетентности и о том, что "классику все-таки по диагонали читать не следует"?
Здравствуйте, samius, Вы писали:
S>Здравствуйте, _FRED_, Вы писали:
_FR>>
_FR>>A collection that is read-only does not allow the addition, removal, or modification of elements after the collection is created.
_FR>>Другое дело, что реализация этого интерфейса массивом неожиданна: несмотря на IsReadOnly = true, изменять данные по индексатору она позволяет. Но, во-первых, это уже детали реализации и, во-вторых, это нигде [я не знаю где] не запрещено документацией. S>Цитата выше утверждает что у read-only коллекций запрещено изменение элементов после создания коллекци без упоминания об исключении в виде массива и его разных реализациях казалось бы одного свойства.
Вопрос к _FRED_'у:
Слав, а можно как-то прокомментировать вот то что написал samius, а то ты как-то скромно оставил именно это предложение без комментариев?
Здравствуйте, Qbit86, Вы писали:
I>>Писал на самом деле не Рихтер, а Krzysztof Cwalina. "Design guidelines."
Q>Тема ветки как бы уточняет название: «Framework Design Guidelines».
Потому что это разные интерфейсы (розетки выглядят по-разному).
А>Считай, что метод Add это вставки вилки в розетку
Если Вам близки аналогии из бытового применения электричества, то пожалуй, следующая аналогия будет корректной:
Вызов метод Add в реализации IList, предоставляемой Массивом -- это вставка вилки мощного нагревательного прибора в розетку на маленьком дизель-генераторе. Вроде как и влазит, но работать не будет (при этом ничего не сломается).
Ну и где-то рядом с розеткой есть табличка "не более 500ватт" для тех, кто инструкцию к дизгену не читает.
Здравствуйте, MozgC, Вы писали:
MC>Здравствуйте, Ikemefula, Вы писали:
I>>Писал на самом деле не Рихтер, а Krzysztof Cwalina. "Design guidelines."
MC>Угу, нашел вот: Generic interfaces, IsReadOnly, IsFixedSize, and array.
MC>
We also decided that arrays will return true from IsReadOnly, but will actually allow setting values using the indexer (which we are trying to fix in RTM as it does not work today).
Уклон все-таки сюда:
We decided that there are really not that many fixed size data structures that are not read only. In fact, we only have one – the array. We think that having a property on a very commonly implemented interface that is useful in only one case is not the right thing to do. So we decided to remove IsFixedSize.
_FRED_ пересказал соображения верно, но промахнулся с источником.
Да, массив всего лишь одна такая стандартная структура. Зато очень часто используемая.
MC>Спорное решение..
и то что оно описано в DG не делает его лучше.
Все равно считаю, что fine-grained разделение интерфейсов коллекций на IReadOnly* и I* позволило бы отказаться от сомнительных свойств IsReadOnly, IsFixedSize без комбинаторного взрыва.
Поезд, правда, ушел. И менять что-либо в интерфейсах стандартных коллекций уже поздно.
Однако, IIndexerSettable — это будет венец всему.
Здравствуйте, samius, Вы писали:
S>Например, в одной из бетта версий (не помню конкретно которой) при кастинге массива в IList<T> получался полностью иммутабельный объект, т.е. через сеттер индексатора IList<T> изменить содержимое массива было нельзя. Однако в документации той же беты было упоминание о том, что не стоит в дальнейшем рассчитывать на такое поведение. Причин отказа от этого решения я не знаю.
О, вот это решение кажется наиболее консистентным.
Здравствуйте, vitasR, Вы писали:
R>Здравствуйте, Аноним, Вы писали:
А>>думаю, проблема в другом — вы мыслите с точки зрения программиста, а я пользователя
R>"пользователь массива" — это звучит гордо!
Здравствуйте, Qbit86, Вы писали:
Q>Это способ избавиться от комбинаторного взрыва.
Это плохой способ избавиться от комбинаторного взрыва.
Он говорит о том, что имеются расфокусированные абстракции.
Здравствуйте, adontz, Вы писали:
A>И как вы предлагаете это реализовать? IList<> может быть поиницилизирован очень далеко, вообще в другом модуле. С какой стати компилятору запрещать вам вызывать метод?
Запрещать нужно не компилятору, а работодателю... нанимать тех кто проектирует такие интерфейсы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, samius, Вы писали:
S>Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
Это и делать не надо. Есть механизм динамического запроса интефрейсов (динамическое приведение типов). От одного интерфейса всегда можно попросить другой даже если между ними нет никакой связи (пример на шарпе):
interface IList2
{
this[int index] { get; }
}
interface IMutableList2
{
this[int index] { get; set; }
}
class MyLis2 : IMutableList2, IList2 { ... }
...
IList2 lst = new MyLis2();
IMutableList2 mutableLst = (IMutableList2)lst;
...
// или с проверкойvar mutableLst = lst as IMutableList2;
if (mutableLst != null)
...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, samius, Вы писали:
S>>Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
VD>Это и делать не надо. Есть механизм динамического запроса интефрейсов (динамическое приведение типов). От одного интерфейса всегда можно попросить другой даже если между ними нет никакой связи (пример на шарпе):
Речь шла о том что коллекция меняет свою мутабельность в динамике. Вот я и вспомнил, про IUnknown.QueryInterface. Правда в COM AFAIR были законы по поводу QE, что в рантайме набор поддерживаемых интерфейсов не меняется для объекта.
Здравствуйте, samius, Вы писали:
A>>Смысла в это всё равно нет, потому что я лично сам встречался со случаями когда коллекция ReadOnly/FixedSize иногда. Интерфейсами такое не обозначить.
S>Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
Это фигня какая то Управление набором интерфейсов — вынос мозга.
Автор Design Guidelines пишет, что надо пользоваться например (obj is Array)
Вообще интерфейсы очень полезная штукенция, пустые интерфейсы это например аццки быстрый аналог атрибутов у класса.
Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, samius, Вы писали:
A>>>Смысла в это всё равно нет, потому что я лично сам встречался со случаями когда коллекция ReadOnly/FixedSize иногда. Интерфейсами такое не обозначить.
S>>Впрочем, можно было бы сделать аналог QueryInterface, который бы в динамике решал, возвращать ли или нет запрашиваемую грань.
I>Это фигня какая то Управление набором интерфейсов — вынос мозга.
+1
I>Автор Design Guidelines пишет, что надо пользоваться например (obj is Array)
это по сути единственный выход, но он гарантирует решение лишь для массива. А что если мне нужно написать Array2?
I>Вообще интерфейсы очень полезная штукенция, пустые интерфейсы это например аццки быстрый аналог атрибутов у класса.
Да, но в том же Guidlines где-то написано что пустые интерфейсы использовать нежелательно. Что мне собственно не мешало их использовать.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, samius, Вы писали:
S>>Речь шла о том что коллекция меняет свою мутабельность в динамике.
VD>Это где это? здесь
Здравствуйте, VladD2, Вы писали:
VD>Заметь, даже множественное наследование не понадобилось. Хотя можно было и его заюзать.
Я о множестве стандартных реализаций на все случаи жизни. Они, кстати, должны ещё уметь агрегировать друг друга, чтобы MutableList можно было кое-кому выдавать как ReadOnlyList. Экспоненциальный рост количестве классов получается без множественного наследования. Да и с них фигня входит в общем-то, но уже другого рода.
Здравствуйте, adontz, Вы писали:
A>Я о множестве стандартных реализаций на все случаи жизни. Они, кстати, должны ещё уметь агрегировать друг друга, чтобы MutableList можно было кое-кому выдавать как ReadOnlyList. Экспоненциальный рост количестве классов получается без множественного наследования. Да и с них фигня входит в общем-то, но уже другого рода.
Не выдумывай. Никакого экспоненциально роста не будет. Будте грамотный дизайн. А то что есть — это бардак.
В одном ты правл, уже вряд ли кто-то что-то станет менять.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, adontz, Вы писали:
A>Здравствуйте, VladD2, Вы писали:
VD>>Не выдумывай. Никакого экспоненциально роста не будет. Будте грамотный дизайн. А то что есть — это бардак.
A>Влад, если бы сам сел и внимательно расписал все классы, то не стал бы спорить. Впрочем с твоим опытом проектирования необходимости в ручке и бумаге быть не должно, так что ты меня попросту удивляешь.
A>Ладно, я сделаю эту работу за тебя. Для полноты картины и в назидание потомкам.
A>
A>public interface IMutableAddRemoveList<T> : IList<T>, IMutableCollection<T>
A>{
A> int Insert(int index, T item);
A> bool RemoveAt(int index);
A>}
A>public interface IMutableModifyList<T> : IList<T>
A>{
A> // Это полностью новое свойство, нельзя доопределить сеттер.
A> T this[int index] { get; set; }
A>}
A>////////////////////////////////////////////////////////////////////////////////
A>// Реализация по умолчанию, как List<T>
A>public class MutableAddRemoveList<T> : IMutableAddRemoveList<T>
A>{
A>...
A>}
A>// Реализация по умолчанию, как List<T>
A>public class MutableModifyList<T> : IMutableModifyList<T>
A>{
A>...
A>}
A>// Реализация по умолчанию, как List<T>
A>// Copy+Paste их двух предыдущих классов.
A>public class MutableList<T> : IMutableAddRemoveList<T>, IMutableModifyList<T>
A>{
A>...
A>}
A>
Это чушь какая-то. Зачем все эти классы? Если у нас скажем SCG.List<T> поддерживает индексированный доступ и изменение, то реализуем в нем IMutableList<T>. Если это скажем однонаправленный связанный список являющийся неизменяемой структурой данных, то реализуем в нем только ICollection<T> и т.д.
A>Уже три класса вместо одного, и двойное повторение кода. В два раза больше кода, полученного обычной копипастой.
Дык ты намеренно глупость же сделал.
A>СВ .Net эта проблема не решается непосредственно.
Да нет никакой проблем на самом то деле. Ты ее сам из пальца высосал.
В прочем, на самом деле нет особой нужды в Mutable-интерфейсах. Вот скажи, ты сам то часто на практике добавлял элементы через IList<T> или ICollection<T>? Я — ни разу. Когда коллекция заполняется, то обычно работа идет с конкретными типами. А вот кода мы ее передам в некий обработчик, то тут хорошо бы иметь дело с абстракцией. Но при этом обычно речь идет о чтении данных, а не об их изменении. По сему на практике в большинстве случаев достаточно IEnumerable<T>. Вот по этому то наличие всех этих лишних методов на практике особых проблем и не вызывает. Но это никак не доказывает необходимость наличия этих методов.
A>Кроме того, что делать с ситуациями, когда доступно операции величина не постоянная? Вот скажем у меня коллекция связана с каким-то хранилищем (БД или что-то ещё) и менять её (писать в хранилище) можно только наложив блокировку. То есть в каких-то случаях (когда блокировки нет) IsReadOnly вернёт true, а Add(T) выбросит InvalidOperationException, а в каких-то других случаях IsReadOnly вернёт false и Add(T) отработает штатно. Как такие сценарии сочетаются с идеей fine grained interfaces?
Это какая-то выдуманная фигня. Что ее разбирать то?
A>То есть, если резюмировать, то что ты предлагаешь вызывает бурный рост количества сущностей, кучу копирования кода при реализации коллекций и лишь частичное покрытие возможных сценариев.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>В прочем, на самом деле нет особой нужды в Mutable-интерфейсах. Вот скажи, ты сам то часто на практике добавлял элементы через IList<T> или ICollection<T>? Я — ни разу.
А я постоянно. Никогда не объявляю переменную конкретного типа за исключением случаев, когда иначе нельзя. Всегда использую самый базовый тип, какой только возможно.
VD>Когда коллекция заполняется, то обычно работа идет с конкретными типами.
Прямо противоположный опыт. В общем ты сам испугался что интерфейсов много и решил оставить только readonly. Совсем не интересный вариант.
A>>Кроме того, что делать с ситуациями, когда доступно операции величина не постоянная? Вот скажем у меня коллекция связана с каким-то хранилищем (БД или что-то ещё) и менять её (писать в хранилище) можно только наложив блокировку. То есть в каких-то случаях (когда блокировки нет) IsReadOnly вернёт true, а Add(T) выбросит InvalidOperationException, а в каких-то других случаях IsReadOnly вернёт false и Add(T) отработает штатно. Как такие сценарии сочетаются с идеей fine grained interfaces?
VD>Это какая-то выдуманная фигня. Что ее разбирать то?
О да, гениальный аргумент. Вообще-то это абсолютно реальная ситуация взятая из рабочего проекта. Её действительно не надо разбирать, она имеет место быть и это надо принять как есть.
Здравствуйте, adontz, Вы писали:
A>А я постоянно. Никогда не объявляю переменную конкретного типа за исключением случаев, когда иначе нельзя. Всегда использую самый базовый тип, какой только возможно.
Зачем?
VD>>Когда коллекция заполняется, то обычно работа идет с конкретными типами.
A>Прямо противоположный опыт. В общем ты сам испугался что интерфейсов много и решил оставить только readonly. Совсем не интересный вариант.
Может стоит подумать над тем что и зачем ты делаешь?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, samius, Вы писали:
A>>Коллекция не всегда создаётся и заполняется в рамках одного метода, так что будьте знакомы — http://en.wikipedia.org/wiki/Interface_segregation_principle S>кстати, да, ISP — еще один довод против существующих интерфейсов. S>
S>Instead of one fat interface many small interfaces are preferred based on groups of methods, each one serving one submodule.
И саго, употреблённое не в меру, может причинить вред.
Здравствуйте, VladD2, Вы писали:
A>>Коллекция не всегда создаётся и заполняется в рамках одного метода, VD>Вот это у тебя косяк в дизайне, да. Старайся так не делать.
Аргументы будут?
A>> так что будьте знакомы — http://en.wikipedia.org/wiki/Interface_segregation_principle VD>Вообще-то конечно жить лучше своими мозгами, но все же ты бы прежде чем давать ссылку почитал бы ее. Это статья как раз о том почему в IList не должно быть Insert().
Вот давай без прыжков в сторону. Речь шла об использовании конкретного типа вместо интерфейса.
A>>Зачем я не сообщаю всем подряд тип класса конкретной реализации? Мне что, действительно придётся это объяснять? VD>Зачем кому-то рассказывать о внутренней реализации?
Вот именно, зачем?
VD>Есть один отличный принцип который я почерпнул из ФП. Если речь идет об обработке данных, то лучше стараться всегда делать ее так чтобы не изменять исходных данных. А к императиву прибегать только когда это оправдано соображениями производительности или иными весомыми соображениями. Тогда весь код по работе с коллекциями резко уходит в глубь методов, а наружу начинают торчать списки (в немерле list[T]) и массивы (копии данных). При этом вопросов с абстрагированием или связанностью не возникает в принципе. Мы ведь всегда работаем с "отключенными" данными (копиями). VD>Так что если я вижу в коде передачу изменяемой коллекции (даже интерфейса) в другой метод, то это сразу же меня настораживает.
Влад, как эти замечательные рассуждения коррелируют с каким-либо байндингом? А, ну да, никак. На Nemerle или ASP.Net мир клином не сошёлся. Бывает необходимо обмениваться изменяемыми коллекциями и это не всегда плохой дизайн, как ты почему-то думаешь.
Здравствуйте, VladD2, Вы писали:
VD>Для меня это настолько очевидно, что я даже затрудняюсь найти доходчивое объяснение. VD>Пока мы меняем коллекцию внутри метода — это проблемы реализации одного метода. Когда мы растягиваем этот процесс по нескольким методам, то начинаем иметь дело с неинкапсулированным состоянием. А это уже не хорошо. Я конечно понимаю, что на языках где нет локальных функций подмывает разбить код (произвести его декомпозицию) на отдельные (хотя бы private) методы. Но все же это плохо. Решаем одну проблему — создаем другую.
Ты умудрился чудесно переврать мои слова. Давай ты попытаешься прочесть это предложение ещё раз — "Коллекция не всегда создаётся и заполняется в рамках одного метода".
VD>Какие прыжки? Изначально мы говорили о том, что интерфейсы коллекций в дотнете криво спроектированы. Ты дал ссылку на кошерное обоснование того, что интерфейсы должны быть маленькими и специализированными, а не толстыми и всеобъемлющими.
Вообще-то там ничего не говориться о больших или маленьких интерфейсах. Размер в ISP вообще не цель и характеристика. Речь там идёт о минимально необходимом интерфейсе.
VD>А вот про конкретные типы я там ничего не углядел.
Не воспринимай слово интерфейс слишком узко. Там не про ключевое слово языка C# говорится.
VD>Ты наверно перепутал этот принцип с простой идеей, что возвращать конекртные изменяемые коллекции из методов не кошерно. С этим я в общем-то согласен. Хотя тоже не вижу в этом ничего плохого, если возвращается копия.
Никакой путаницы нет, твоя простая идея есть элементарный вывод из существования ISP. Копирование и уточнение типа перпендикулярны.
VD>Дык ты это и предлагаешь. Причем думаешь, что если спрятать изменяемый индексируемый список за интерфейсом, то это решит проблему. Не решит. Ты конечно получишь гипотетический бенефит от того, что сможешь сменить реализацию коллекции не трогая другого кода. Но плюешь на куда более серьезную проблему размазывания императивного алгоритма по разным методам. Императив нужно инкапсулирвоать.
А кто тебе сказал что есть какое-либо размазывание?
VD>И кстати, если бы ты передавал именно IMutableList, то по сигнатуре метода уже можно было бы понять, что он будет менять этот список, а значит с данным методом нужно быть как можно акуратнее. А так ты передаешь IList и в те методы что просто нуждаются в списке, и в те, что собираются его изменять. Это явное использование абстракции на вред себе любимому. Это ничем не отличается от передачи IMutableList методу который не собирается менять данные.
Это весьма и весьма надуманная проблема. Метод Append меняет коллекцию, метод Print — нет. Смотреть в его параметры не обязательно. И ты ктати не упрощай, ты сейчас про IAddRemoveMutableList говорил или про IModifyMutableList?
VD>Дык и неизменяемыми структурами данных можно обмениваться без проблем. В конце концов любое изменение можно рассматривать как удаление старого объекта и вставку нового. Так что на входе имеем список с исходными объектами, на выходе новый где часть объектов старые, а часть новые (ставленные или замененные). При этом очень легко сделать между ними diff и получить третий список содержащий только изменения.
Ага, то есть стоимость изменения одного элемента массива — O(N). А потом говорят что .Net тормозит.
VD>Потом на ГУИ свет клином не сошелся. ГУЯ не так много в серьезных задачах. Обработка данных обычно занимает куда больше места и времени (программиста). И тут вопросы биндига уже не будут актуальны.
Ну не GUI, так службы. Я и не гвоорил только про GUI.
Здравствуйте, adontz, Вы писали:
A>Ты умудрился чудесно переврать мои слова. Давай ты попытаешься прочесть это предложение ещё раз — "Коллекция не всегда создаётся и заполняется в рамках одного метода".
И? Не, ну, я понимаю если твоя коллекция является состоянием некого объекта. Тогда она будет полем и тогда ее и передавать то никуда не надо будет. Хотя и тут я бы не стал заполнять ее во многих местах. Но зачем коллекции через параметры то передавать?
VD>>Какие прыжки? Изначально мы говорили о том, что интерфейсы коллекций в дотнете криво спроектированы. Ты дал ссылку на кошерное обоснование того, что интерфейсы должны быть маленькими и специализированными, а не толстыми и всеобъемлющими.
A>Вообще-то там ничего не говориться о больших или маленьких интерфейсах. Размер в ISP вообще не цель и характеристика.
Это вот от туда:
The ISP says that once an interface has gotten too 'fat' it needs to be split into smaller and more specific interfaces so that any clients of the interface will only know about the methods that pertain to them. In a nutshell, no client should be forced to depend on methods it does not use.
и это тоже:
Martin Fowler's name for smaller interfaces which only include the needed methods is 'Role Interface'.
или вот еще краткое определение: the notion that “many client specific interfaces are better than one general purpose interface
A>Речь там идёт о минимально необходимом интерфейсе.
Там речь о самих интерфейсах. Лучше иметь больше специализированных интерфейсов нежели один общего назначения.
Это как раз о том, что лучше иметь IImutableList и IMutableList нежели один общий IList.
VD>>А вот про конкретные типы я там ничего не углядел.
A>Не воспринимай слово интерфейс слишком узко. Там не про ключевое слово языка C# говорится.
Да я как раз его то воспринимаю совершенно адекватно. А вот ты явно понимаешь этот самый ISP как-то односторонне.
VD>>Ты наверно перепутал этот принцип с простой идеей, что возвращать конекртные изменяемые коллекции из методов не кошерно. С этим я в общем-то согласен. Хотя тоже не вижу в этом ничего плохого, если возвращается копия.
A>Никакой путаницы нет, твоя простая идея есть элементарный вывод из существования ISP. Копирование и уточнение типа перпендикулярны.
Что-то я совсем запутался в твой геометрии. Что кому перпендикулярно, а что параллельно?
VD>>Дык ты это и предлагаешь. Причем думаешь, что если спрятать изменяемый индексируемый список за интерфейсом, то это решит проблему. Не решит. Ты конечно получишь гипотетический бенефит от того, что сможешь сменить реализацию коллекции не трогая другого кода. Но плюешь на куда более серьезную проблему размазывания императивного алгоритма по разным методам. Императив нужно инкапсулирвоать.
A>А кто тебе сказал что есть какое-либо размазывание?
Ты же вроде бы коллекции между методами передавать предлагал. Нет?
VD>>И кстати, если бы ты передавал именно IMutableList, то по сигнатуре метода уже можно было бы понять, что он будет менять этот список, а значит с данным методом нужно быть как можно акуратнее. А так ты передаешь IList и в те методы что просто нуждаются в списке, и в те, что собираются его изменять. Это явное использование абстракции на вред себе любимому. Это ничем не отличается от передачи IMutableList методу который не собирается менять данные.
A>Это весьма и весьма надуманная проблема.
Ну, как знаешь. Приведенный тобой же пницип ISP как раз говорит, что в интерфейсе не должно быть не используемых методов.
A>Метод Append меняет коллекцию, метод Print — нет.
А вот это уже твое вооражение. Сколько раз я видел когда очевидные (казалось бы) предположения не подтверждались на практике. Твой ISP как раз говорит о том, что теорию лучше подкреплять железными мерами.
A>Смотреть в его параметры не обязательно.
Дык если все сделано по-человечески то и смотреть не надо будет. Если метод возвратил неизменяемый интерфейс, то можно быть уверенным, что никто его не попытается менять.
A>И ты ктати не упрощай, ты сейчас про IAddRemoveMutableList говорил или про IModifyMutableList?
Это какой-то странный выбор меду бредом и делириумом.
A>Ага, то есть стоимость изменения одного элемента массива — O(N). А потом говорят что .Net тормозит.
О! А вот и преждевременные оптимизации.
Кстати о них родных и за одно о парсере. Сегодня Ziaw опубликовал
свои тесты по которым выходит, что написанный на нашем PegGrammar за пару часов парсер джейсона оказался в полтора раза быстрее Json.NET в котором парсер джейсона написан на шарпе вручную. При этом наш парсер как не парадоксально написан в функциональном стиле (т.е., по-твоему, тормозно). Я уже не говорю о том, что их парсер — это тысяча с гаком строк код кода, в то время как немерловый описывается декларативной грамматикой.
A>Ну не GUI, так службы. Я и не гвоорил только про GUI.
Что за службы такие которым нужен биндинг?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Это вот от туда: VD>The ISP says that once an interface has gotten too 'fat' it needs to be split into smaller and more specific interfaces so that any clients of the interface will only know about the methods that pertain to them. In a nutshell, no client should be forced to depend on methods it does not use. VD>и это тоже: VD>Martin Fowler's name for smaller interfaces which only include the needed methods is 'Role Interface'. VD>или вот еще краткое определение: VD>the notion that “many client specific interfaces are better than one general purpose interface A>>Речь там идёт о минимально необходимом интерфейсе. VD>Там речь о самих интерфейсах. Лучше иметь больше специализированных интерфейсов нежели один общего назначения.
Видимо прочесть "so that any clients of the interface will only know about the methods that pertain to them" ты не удосужился.
VD>Это как раз о том, что лучше иметь IImutableList и IMutableList нежели один общий IList.
Если есть клиенты требующие один из этих интерфейсов без другого, то да. Разделение не самоцель. Не путай ISP с SRP.
A>>Никакой путаницы нет, твоя простая идея есть элементарный вывод из существования ISP. Копирование и уточнение типа перпендикулярны. VD>Что-то я совсем запутался в твой геометрии. Что кому перпендикулярно, а что параллельно?
Для того чтобы передать копию данных нет необходимости явно предавать какой-то конкретный класс вместо интерфейса. Твоё желание пользоваться классами при изменении данных никак не может быть аргументировано необходимостью копирования.
A>>А кто тебе сказал что есть какое-либо размазывание? VD>Ты же вроде бы коллекции между методами передавать предлагал. Нет?
И что? Я обработал данные в одном месте, передал в другое, там тоже обработал, передал в третье... эти обработки могут быть совершенно не связаны, даже не знать друг о друге, даже не быть строго последовательными. Никакого размазывания логики тут нет. Много разных логик, общие данные.
A>>Это весьма и весьма надуманная проблема. VD>Ну, как знаешь. Приведенный тобой же пницип ISP как раз говорит, что в интерфейсе не должно быть не используемых методов.
Не примешивай ISP к вопросам семантики.
A>>Метод Append меняет коллекцию, метод Print — нет.
VD>Сколько раз я видел когда очевидные (казалось бы) предположения не подтверждались на практике.
Тоже самое можно сказать и о твоих словах. Тем не менее, по выразительности английский язык лучше иерархии интерфейсов. Кроме того, операции и данные не взаимно однозначны. И вообще, если твой подход работает, то почему нет константных аргументов как в Си++?
A>>И ты ктати не упрощай, ты сейчас про IAddRemoveMutableList говорил или про IModifyMutableList? VD>Это какой-то странный выбор меду бредом и делириумом.
О нет, это светлое будущее к которому ты призываешь!
A>>Ага, то есть стоимость изменения одного элемента массива — O(N). А потом говорят что .Net тормозит. VD>О! А вот и преждевременные оптимизации. VD>Кстати о них родных и за одно о парсере. Сегодня Ziaw опубликовал
свои тесты по которым выходит, что написанный на нашем PegGrammar за пару часов парсер джейсона оказался в полтора раза быстрее Json.NET в котором парсер джейсона написан на шарпе вручную. При этом наш парсер как не парадоксально написан в функциональном стиле (т.е., по-твоему, тормозно). Я уже не говорю о том, что их парсер — это тысяча с гаком строк код кода, в то время как немерловый описывается декларативной грамматикой.
А вообще к чему этот аргумент если AST — это дерево, элементы которого не модифицируются, а мы говорим про массив элементы которого модифицируются? Не, я рад что вы научились быстро разбирать Json, но какое это вообще имеет отношение к теме разговора?
A>>Ну не GUI, так службы. Я и не гвоорил только про GUI. VD>Что за службы такие которым нужен биндинг?
Observable Collections. На оповещения могут подписываться не только ЭУ.