Re[43]: Создание объекта по ID
От: fmiracle  
Дата: 27.04.10 11:19
Оценка:
Здравствуйте, igna, Вы писали:

_FR>>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает).

I>То, что "конструктор с capacity делает чего такого", не обязывает его быть открытым.

Но желание применить возможности, которые дает конструктор с capacity (а именно, оптимизация быстродействия), обязывает его быть открытым.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[10]: Создание объекта по ID
От: igna Россия  
Дата: 27.04.10 11:23
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Конструктор с указываемой Capacity интересен именно как открытый.


Он может быть закрытый и вызываться открытым статическим методом. Такая комбинация закрытого конструктора и открытого статического метода популярна, поэтому я сначала ответил кратко, без подробностей.
Re[42]: Создание объекта по ID
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.04.10 11:56
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


S>>Согласен, что так понятнее. Но исторически конструктор List<T>(IEnumerablt<T>) появился раньше метода ToList(). Кроме этого я подозреваю что сей конструктор мог предназначаться для наследников от List<T>. Я знаю, что List<T> не предназначался для наследования, но и sealed он не помечен. Да и AFAIR в msdn попадались примеры с наследованием от него.


_FR>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает).

Речь о методах AddRange(IEnumerable<T>) и InsertRange(Int32, IEnumerable<T>) ???
Если да, то что такого делает конструктор с capacity, чего нельзя было бы сделать через публичный сеттер Capacity?

_FR>А в [открытый] интерфейс типа без крайней необходимости вообще лучше не добавлять ничего, чего нельзя было бы сделать без имеющегося [открытого] интерфейса.

Что такого крайнего с capacity?
Re[43]: Создание объекта по ID
От: _FRED_ Черногория
Дата: 27.04.10 12:16
Оценка:
Здравствуйте, samius, Вы писали:

_FR>>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает).

S>Речь о методах AddRange(IEnumerable<T>) и InsertRange(Int32, IEnumerable<T>) ???

Да даже без них на одном IList<>::Add можно было бы реализовать

S>Если да, то что такого делает конструктор с capacity, чего нельзя было бы сделать через публичный сеттер Capacity?


устанавливает все-лишь начальный размер. То есть код
var list = new List<X>(5);

отличается от
var list = new List<X>() { Capacity = 5, };

лишь тем, что во втором случае сначала будет создан массив с дефолтовым Capacity, а потом будет создан новый массив с требуемым capacity. В первом случае сразу же создаётся массив с нужным capacity. Это, конечно же, мелочи, о них я упомянул только для тех, кто любит придираться.

А по большому счёту, и от конструктора с capacity сейчас (при наличии object initializers) можно было бы отказаться.
Help will always be given at Hogwarts to those who ask for it.
Re[11]: Создание объекта по ID
От: fmiracle  
Дата: 27.04.10 12:25
Оценка:
Здравствуйте, igna, Вы писали:

F>>Конструктор с указываемой Capacity интересен именно как открытый.

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

Если этот статический метод вызывает ровно закрытый конструктор с теми же аргументами, что и у данного метода, то, совершенно очевидно, что данный статический метод — излишен.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[44]: Создание объекта по ID
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.04.10 12:26
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


_FR>>>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает).

S>>Речь о методах AddRange(IEnumerable<T>) и InsertRange(Int32, IEnumerable<T>) ???

_FR>Да даже без них на одном IList<>::Add можно было бы реализовать


S>>Если да, то что такого делает конструктор с capacity, чего нельзя было бы сделать через публичный сеттер Capacity?


_FR>устанавливает все-лишь начальный размер. То есть код

_FR>
_FR>var list = new List<X>(5);
_FR>

_FR>отличается от
_FR>
_FR>var list = new List<X>() { Capacity = 5, };
_FR>

_FR>лишь тем, что во втором случае сначала будет создан массив с дефолтовым Capacity, а потом будет создан новый массив с требуемым capacity. В первом случае сразу же создаётся массив с нужным capacity. Это, конечно же, мелочи, о них я упомянул только для тех, кто любит придираться.

Я не любитель, но придется придраться.
Конструкторы с collection и capacity в одинаковом положении. Конструктор с collection позволяет избежать создания массива с дефолтовым Capacity в случае когда collection is ICollection<T>. Т.е. как и конструктор с capacity он делает что-то такое, что без него сделать нельзя (C) (см. выше выделенное)

_FR>А по большому счёту, и от конструктора с capacity сейчас (при наличии object initializers) можно было бы отказаться.

Уже нет. Легаси.
Re[12]: Создание объекта по ID
От: fmiracle  
Дата: 27.04.10 12:27
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Если этот статический метод вызывает ровно закрытый конструктор с теми же аргументами, что и у данного метода, то, совершенно очевидно, что данный статический метод — излишен.


Нет, боюсь примотаешься к какому слову — допишу еще немного — "и этот метод не делает ничего больше, кроме как вызов этого самого конструктора, который с теми же самыми аргументами".
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[13]: Создание объекта по ID
От: igna Россия  
Дата: 27.04.10 12:55
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>"и этот метод не делает ничего больше, кроме как вызов этого самого конструктора, который с теми же самыми аргументами".


То есть все же бывают случаи, когда конструктор с указываемой Capacity интересен не только как открытый.
Re[45]: Создание объекта по ID
От: _FRED_ Черногория
Дата: 27.04.10 12:59
Оценка:
Здравствуйте, samius, Вы писали:

S>Конструкторы с collection и capacity в одинаковом положении. Конструктор с collection позволяет избежать создания массива с дефолтовым Capacity в случае когда collection is ICollection<T>. Т.е. как и конструктор с capacity он делает что-то такое, что без него сделать нельзя (C) (см. выше выделенное)


Ну это же очень просто:

        public static List<T> Create<T>(IEnumerable<T> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            var collection = source as ICollection<T>;
            var list = (collection != null) ? new List<T>(collection.Count) : new List<T>();
            foreach (var item in source)
            {
                list.Add(item);
            }
            return list;
        }

тут никакого перераспределения памяти не будет, разница лишь (в некоторых случаях — когда известен Count) в ручной прокрутке source вместо Array.Copy(…).
Help will always be given at Hogwarts to those who ask for it.
Re[44]: Создание объекта по ID
От: igna Россия  
Дата: 27.04.10 13:00
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Но желание применить возможности, которые дает конструктор с capacity (а именно, оптимизация быстродействия), обязывает его быть открытым.


Продолжение здесь
Автор: fmiracle
Дата: 27.04.10
.
Re[46]: Создание объекта по ID
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.04.10 13:14
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


S>>Конструкторы с collection и capacity в одинаковом положении. Конструктор с collection позволяет избежать создания массива с дефолтовым Capacity в случае когда collection is ICollection<T>. Т.е. как и конструктор с capacity он делает что-то такое, что без него сделать нельзя (C) (см. выше выделенное)


_FR>Ну это же очень просто:


_FR>
_FR>        public static List<T> Create<T>(IEnumerable<T> source)
_FR>        {
_FR>            if (source == null)
_FR>            {
_FR>                throw new ArgumentNullException("source");
_FR>            }

_FR>            var collection = source as ICollection<T>;
_FR>            var list = (collection != null) ? new List<T>(collection.Count) : new List<T>();
_FR>            foreach (var item in source)
_FR>            {
_FR>                list.Add(item);
_FR>            }
_FR>            return list;
_FR>        }
_FR>

_FR>тут никакого перераспределения памяти не будет, разница лишь (в некоторых случаях — когда известен Count) в ручной прокрутке source вместо Array.Copy(…).

Ну вот, лишнего перераспределения избежать удалось, но эффективное копирование может организовать лишь конструктор List<T>(IEnumerable<T>). На больших размерах коллекций это сыграет куда сильнее, чем лишнее перераспределение. А InsertRange делает лишние копирования.
Re[46]: Создание объекта по ID
От: igna Россия  
Дата: 27.04.10 13:37
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>        public static List<T> Create<T>(IEnumerable<T> source)
_FR>        {
_FR>            if (source == null)
_FR>            {
_FR>                throw new ArgumentNullException("source");
_FR>            }

_FR>            var collection = source as ICollection<T>;
_FR>            var list = (collection != null) ? new List<T>(collection.Count) : new List<T>();
_FR>            foreach (var item in source)
_FR>            {
_FR>                list.Add(item);
_FR>            }
_FR>            return list;
_FR>        }


У меня вопрос не имеющий отношения к контексту. Ты на самом деле пишешь так вместо перегрузки?:

        static void checkSource(source) {
            if (source == null)
                throw new ArgumentNullException("source");
        }

        static List<T> fillList(IEnumerable<T> source, List<T> list) {
            foreach (var item in source)
                list.Add(item);
            return list;
        }

        public static List<T> Create<T>(IEnumerable<T> source) {
            checkSource();
            return fillList(source, new List<T>());
        }

        public static List<T> Create<T>(ICollection<T> source) {
            checkSource();
            return fillList(source, new List<T>(source.Count));
        }
Re[47]: Создание объекта по ID
От: _FRED_ Черногория
Дата: 27.04.10 13:40
Оценка:
Здравствуйте, samius, Вы писали:

S>Ну вот, лишнего перераспределения избежать удалось, но эффективное копирование может организовать лишь конструктор List<T>(IEnumerable<T>).


А что в этом копировании неэффективного?

S>На больших размерах коллекций это сыграет куда сильнее, чем лишнее перераспределение.


Что ты называешь "больших"? Будет ли при указанных размерах вообще эффективным использование List<>? Ибо добавление одного элемента в "болшой" список может вызвать копирование имеющегося буфера. Поиск (ввиду линейной сложности, то есть полного перебора) практически бессмысленен.
Help will always be given at Hogwarts to those who ask for it.
Re[48]: Создание объекта по ID
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.04.10 13:58
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, samius, Вы писали:


S>>Ну вот, лишнего перераспределения избежать удалось, но эффективное копирование может организовать лишь конструктор List<T>(IEnumerable<T>).


_FR>А что в этом копировании неэффективного?


Что именно неэффективного — это уж оффтоп. Но по сравнению с ICollection<T>.CopyTo(T[], Int32) в некоторых случаях (например в случае копирования из T[]) будет заметно сливать.

S>>На больших размерах коллекций это сыграет куда сильнее, чем лишнее перераспределение.


_FR>Что ты называешь "больших"? Будет ли при указанных размерах вообще эффективным использование List<>?


Я не имею ввиду никаких конкретных сценариев. Просто мы заговорили о том что якобы даже лишнее перераспределение массива может продиктовать наличие конструктора с capacity. И я тут пытаюсь сказать что конструктор с IEnumerable<T> возможно существует по причинам производительности. Другие способы добавления в IList<T> условно больших коллекций будут менее эффективны хоть на 10-и, хоть на 1М элементов. Они будут медленнее не идеологически, а просто в силу реализации.

Менее эффективны == займут больше времени. Но я не предлагаю устраивать бенчмарки. В большинстве сценариев меня лично устраивает метод Enumerable.ToList() и мне даже не особо любопытно, использует ли он конструктор или нет. Знаю что использует, но если бы не использовал, я бы не перестал пользоваться этим методом.

_FR>Ибо добавление одного элемента в "болшой" список может вызвать копирование имеющегося буфера. Поиск (ввиду линейной сложности, то есть полного перебора) практически бессмысленен.

После использования конструктора List<T>(IEnumerable<T>) добавление одного элемента непременно вызовет перераспределение. Но связка new List<T>(Int32) + Add(T) может оказаться медленнее.
Re[40]: Создание объекта по ID
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 27.04.10 14:21
Оценка: :)
Здравствуйте, _FRED_, Вы писали:

_FR>Допускает или нет — зависит не от типов параметров, а от того, как переданный массив используется. По одному объявлению ответить на вопрос невозможно.


Наоборот, использование в конструкторе предполагает определенное использование.

_FR>Давай с классом List<> разберёмся (поскольку его реализация нам известна), вернее с его конструктором List<>(IEnumerable<>). Я бы не добавлял такой [открытый] конструктор в класс, а конструирование списка из IEnumerable<> возложил бы на статический метод. Потому что такой вот код:

_FR>
_FR>void Test(MyBusinessEntitiesCollection<MyEntity> items) {
_FR>  var list = new List<MyEntity>(items);
_FR>  var collection = new Collection<MyEntity>(items);
_FR>}
_FR>

_FR>мне не нравится — через конструктор не передаётся связь между аргументом и созданным объектом. В первом случае происходит копирование, а во-втором — создаётся обёртка-декоратор.

_FR>Вот так вот, имхо, было бы гораздо понятнее:


Collection принимает IList<T> а не IEnumerable, тк что твой пример не сильно удачный.
Re[43]: Создание объекта по ID
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 27.04.10 14:22
Оценка:
Здравствуйте, igna, Вы писали:

_FR>>ИМХО, очень сомнительный вывод. Впрочем, даже в этом топике не в первый раз, так что тролль себе дальше.


I>А зачем? Пока была вероятность, что правило Фреда имеет смысл, я пытался разобраться. А теперь все ясно. Но спасибо за разъяснения, другие просто убежали, почувствовав понятно что.


А ты случаем себе в зеркале не улыбаешься ?
Re[42]: Создание объекта по ID
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 27.04.10 14:35
Оценка: :)
Здравствуйте, _FRED_, Вы писали:

_FR>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает). А в [открытый] интерфейс типа без крайней необходимости вообще лучше не добавлять ничего, чего нельзя было бы сделать без имеющегося [открытого] интерфейса.


Если IEnumerable в конструкторе контейнера и хранит аккурат то, что будет непосредтсвенно храниться в контейнере то это и есть такая необходимость.
Re[14]: Создание объекта по ID
От: fmiracle  
Дата: 27.04.10 14:47
Оценка:
Здравствуйте, igna, Вы писали:

F>>"и этот метод не делает ничего больше, кроме как вызов этого самого конструктора, который с теми же самыми аргументами".

I>То есть все же бывают случаи, когда конструктор с указываемой Capacity интересен не только как открытый.

Это к чему?

Бывают случаи, когда конструктор с указываемой Capacity интересен как открытый. Внешний вызов требует лишнего пересоздания внутреннего буффера.

И при этом ничем тот же функционал не заменишь, кроме просто открытого метода, которая не делает ничего, помимо вызова этого конструктора. Так зачем ее городить, а не просто сделать открытый конструктор?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[15]: Создание объекта по ID
От: igna Россия  
Дата: 27.04.10 15:01
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>И при этом ничем тот же функционал не заменишь, кроме просто открытого метода, которая не делает ничего, помимо вызова этого конструктора. Так зачем ее городить, а не просто сделать открытый конструктор?


Согласен. Но вряд ли это тот случай, когда "конструктор — это метод, в который передаётся некоторое начальное состояние объекта". Capacity это не состояние, а подсказка, hint.
Re[16]: Создание объекта по ID
От: fmiracle  
Дата: 27.04.10 15:33
Оценка:
Здравствуйте, igna, Вы писали:

I>Согласен. Но вряд ли это тот случай, когда "конструктор — это метод, в который передаётся некоторое начальное состояние объекта". Capacity это не состояние, а подсказка, hint.


Хм? Этот параметр именно определяет какое будет внутреннее состояние (размер выделенного внутреннего массива).
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.