P>class Ticket
P>{
P> public Ticket(int id) {}
P> public static Ticket InitTicket(int id) {}
P> public static explicit operator Ticket(int id) {}
P>}
P>
P>каковы доводы в пользу того или иного метода инициализации экземпляра объекта по ID?
1 Вариант — хорош только если вы создаете новый, а только затем наполняете его данными. Ни в коем случае нельзя применять, если у вас там заложена куча логики, и в том числе с exception. Для пользователя класса — логика совершенно неясная.
2 Уже более менее. Заметно что это функция, которая может быть достаточно тяжелой.
3. Ваще не вариант, ибо кака. Даже описывать не буду.
Лучший:
class TicketFactory//TicketController, TicketManager, TicketDAL и т.п по желанию
{
Ticket TicketFactory::CreateTicket(int id)
Ticket LoadTicket(int id)
}
Здравствуйте, barn_czn, Вы писали:
_>public static Ticket Create(int id) {} — так делают но чем лучше (хуже) предыдущего варианта не скажу
Это, по сути, фабричный метод.
По сравнению с предыдущим вариантом позволяет создавать, в зависимости от внешних факторов, не только Ticket, но и любого его наследника. Иногда это очень важно. Иногда нет.
Собственно оригинальный вопрос бессмысленнен. Разные задачи требуют разных решений...
Здравствуйте, samius, Вы писали:
S>Вижу справился с 3-го раза с ответом. Теперь позови народ их форума C++, пусть тебе оценок наставят за внимательность!
Не кормите троля (с)
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, igna, Вы писали:
_FR>>Давай с классом List<> разберёмся (поскольку его реализация нам известна), вернее с его конструктором List<>(IEnumerable<>). Я бы не добавлял такой [открытый] конструктор в класс, а конструирование списка из IEnumerable<> возложил бы на статический метод.
I>Вот. Но кое-кто из согласных с твоим правилом твоего мнения по поводу этого конкретного конструктора не разделяет:
… I>То есть правило нечеткое.
ИМХО, очень сомнительный вывод. Впрочем, даже в этом топике не в первый раз, так что тролль себе дальше.
Help will always be given at Hogwarts to those who ask for it.
P>class Ticket
P>{
P> public Ticket(int id) {}
P> public static Ticket InitTicket(int id) {}
P> public static explicit operator Ticket(int id) {}
P>}
P>каковы доводы в пользу того или иного метода инициализации экземпляра объекта по ID?
Второй вариант, помимо уже сказанного выше, имеет смысл применять тогда, когда аргументы, по которым создаётся экземпляр, не имеют непосредственного отношения к создаваемому объекту. То есть, если значения, переданные в качестве параметров конструктора не хранятся потом в самом объекте, то лучше заменить такой конструктор обычным методом.
Семантика такая: конструктор — это метод, в который передаётся некоторое "начальное" состояние объекта, а статический конструирующий метод — это некий "конвертер" из одних данных (аргументов) в другие — созданный экземпляр.
Третий вариант имеет смысл применять в случаях, когда объект у вас — это и есть целое число, а не что-то, что можно сконструировать по целому числу.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, samius, Вы писали:
I>>>Кроме того, свойство Collection для конструктора List<T>(IEnumerable<T>) у списка есть? S>>Ну а причем тут свойство Collection? Список хранит набор переданных значений. Что именно не нравится?
I>"В качестве параметра" был передан IEnumerable<T>, конструктор использует его, чтобы получить "набор переданных значений", но не хранит сам параметр.
Вижу справился с 3-го раза с ответом. Теперь позови народ их форума C++, пусть тебе оценок наставят за внимательность!
Здравствуйте, _FRED_, Вы писали:
_FR>А по какой причине? Я не просто так спрашиваю, ибо это действительно важно, что бы мы все понимали, о чём ведём речь.
Я не готов отвечать, сначала хочу удостоверится, что понял правило, предлагаемое тобой, верно; поэтому и спрашиваю, как оно будет работать в конкретных случаях.
Здравствуйте, _FRED_, Вы писали:
_FR>Здравствуйте, igna, Вы писали:
I>>допускает ли твое правило MyStringCollection(string[]) или нет.
_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>Вот так вот, имхо, было бы гораздо понятнее: _FR>
_FR>void Test(MyBusinessEntitiesCollection<MyEntity> items) {
_FR> var list1 = items.ToList(); // "To" - значит скопировали
_FR> var list2 = List.Create(items);
_FR> var collection = new Collection<MyEntity>(items);
_FR> var collection2 = items.AsMyDecorator(); // "As" - обернули
_FR>}
_FR>
Согласен, что так понятнее. Но исторически конструктор List<T>(IEnumerablt<T>) появился раньше метода ToList(). Кроме этого я подозреваю что сей конструктор мог предназначаться для наследников от List<T>. Я знаю, что List<T> не предназначался для наследования, но и sealed он не помечен. Да и AFAIR в msdn попадались примеры с наследованием от него.
Здравствуйте, samius, Вы писали:
I>>>допускает ли твое правило MyStringCollection(string[]) или нет. _FR>>Допускает или нет — зависит не от типов параметров, а от того, как переданный массив используется. По одному объявлению ответить на вопрос невозможно. S>Я полагаю, что параметром передается массив имен файлов.
Несомненно. Но тема кодировки не раскрыта
S>Согласен, что так понятнее. Но исторически конструктор List<T>(IEnumerablt<T>) появился раньше метода ToList(). Кроме этого я подозреваю что сей конструктор мог предназначаться для наследников от List<T>. Я знаю, что List<T> не предназначался для наследования, но и sealed он не помечен. Да и AFAIR в msdn попадались примеры с наследованием от него.
Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает). А в [открытый] интерфейс типа без крайней необходимости вообще лучше не добавлять ничего, чего нельзя было бы сделать без имеющегося [открытого] интерфейса.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _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) можно было бы отказаться.
Уже нет. Легаси.
Здравствуйте, _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, тк что твой пример не сильно удачный.
Здравствуйте, _FRED_, Вы писали:
_FR>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает). А в [открытый] интерфейс типа без крайней необходимости вообще лучше не добавлять ничего, чего нельзя было бы сделать без имеющегося [открытого] интерфейса.
Если IEnumerable в конструкторе контейнера и хранит аккурат то, что будет непосредтсвенно храниться в контейнере то это и есть такая необходимость.
Здравствуйте, peer, Вы писали:
P>Имеем
P>[c#] P>class Ticket P>{ P> public Ticket(int id) {}
нормальный подход. в случае чего кидаете эксепшн
P> public static Ticket InitTicket(int id) {}
название фигня, Init подразумевает наличие инстанса.
public static Ticket Create(int id) {} — так делают но чем лучше (хуже) предыдущего варианта не скажу
P> public static explicit operator Ticket(int id) {}
Здравствуйте, peer, Вы писали:
P> public Ticket(int id) {}
Имхо самый нормальный вариант. Семантика конструктора и подразумевает конструирование объекта Ticket на основании входных данных id.
P> public static Ticket InitTicket(int id) {}
Это уже фабричный метод, их обычно используют, если неизвестно, экземпляр какого класса-наследника Ticket (ну или самого класса Ticket) должен быть создан в зависимости от контекста. Пример: метод WebRequest.Create(string), который создаёт объект нужного типа-наследника в зависимости от параметра.
P> public static explicit operator Ticket(int id) {}
А это вообще изврат. Перегружать операторы приведения типа к/из int лучше только если класс, для которого перегружается оператор, тоже представляет собой число, грубо говоря. Иначе возникнет путаница.
P>class Ticket
P>{
P> public Ticket(int id) {}
P> public static Ticket InitTicket(int id) {}
P> public static explicit operator Ticket(int id) {}
P>}
P>
P>каковы доводы в пользу того или иного метода инициализации экземпляра объекта по ID?
Вариант 1: никак нельзя. Компилятор может запросто "случайно" создать лишний объект класса там, где не надо, если посчитает это нужным. По-хорошему, только explicit конструкторы, если на входе простое значение.
Лучше что-нибудь типа
class Ticket
{
public static Ticket* instance(int id) {}
}
Ticket *t = Ticket::instance(id);
Здравствуйте, March_rabbit, Вы писали:
P>>каковы доводы в пользу того или иного метода инициализации экземпляра объекта по ID? M_>Вариант 1: никак нельзя. Компилятор может запросто "случайно" создать лишний объект класса там, где не надо, если посчитает это нужным.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, March_rabbit, Вы писали:
M_>>Компилятор может запросто "случайно" создать лишний объект класса... S>Это как?
сразу хороший пример в голову не приходит, это надо смотреть в книгах типа "Эффективное использование С++" Скотта Майерса и прочих.
что-то типа вот этого:
class T {
public:
T (int i):
m_i(i) {};
int value() const {return m_i; };
private:
int m_i;
};
const T& func(const T& val)
{
int vali = 10;
return vali;
}
//int main ( int, char ** ) {
T v(1);
std::cout << "value: " << func(v).value() << std::endl;
}
Вопрос: что будет выведено в качестве значения?
естественно, пример надуман. В реальности ошибки прячутся гораздо лучше
Но идея показана. Ошибка в одном символе, проигнорирована пара предупреждений компилятора и новый объект родился.
Здравствуйте, _FRED_, Вы писали:
_FR>То есть, если значения, переданные в качестве параметров конструктора не хранятся потом в самом объекте, то лучше заменить такой конструктор обычным методом.
List<T> имеет три конструктора:
List<T>()
List<T>(IEnumerable<T>)
List<T>(Int32)
Какие из них следовало бы заменить обычными методами?
Здравствуйте, igna, Вы писали:
_FR>>То есть, если значения, переданные в качестве параметров конструктора не хранятся потом в самом объекте, то лучше заменить такой конструктор обычным методом.
I>List<T> имеет три конструктора:
Здравствуйте, igna, Вы писали:
_FR>>А какие возникают сомнения?
I>List<T>(Int32)
I>"если значения, переданные в качестве параметров конструктора не хранятся потом в самом объекте, то лучше заменить такой конструктор обычным методом"
Ну почему я должен за вас догадываться о том, что у вас на уме и что вам лень сказать? ИМХО, это неуважение к собеседнику
Здравствуйте, igna, Вы писали:
I>Здравствуйте, _FRED_, Вы писали:
_FR>>Параметр этого конструктора — capacity списка. У списка есть такое свойство, как Capacity.
I>А значение Capacity обязано "хранятся потом в самом объекте"? Это ведь дело реализации, можно ведь и пройти список и посчитать.
Конструктор — это тоже дело реализации
I>Кроме того, свойство Collection для конструктора List<T>(IEnumerable<T>) у списка есть?
Ну а причем тут свойство Collection? Список хранит набор переданных значений. Что именно не нравится?
Здравствуйте, samius, Вы писали:
I>>Кроме того, свойство Collection для конструктора List<T>(IEnumerable<T>) у списка есть? S>Ну а причем тут свойство Collection? Список хранит набор переданных значений. Что именно не нравится?
"В качестве параметра" был передан IEnumerable<T>, конструктор использует его, чтобы получить "набор переданных значений", но не хранит сам параметр. А то так ведь и имя файла можно конструктору передать, откуда значения читать. Или это правилом разрешено?
Здравствуйте, samius, Вы писали:
S>Вижу справился с 3-го раза с ответом. Теперь позови народ их форума C++, пусть тебе оценок наставят за внимательность!
А какой смысл формулировать правила, которые нужно понимать не так, как они написаны, а как-то иначе?
Здравствуйте, igna, Вы писали:
I>Здравствуйте, samius, Вы писали:
S>>Вижу справился с 3-го раза с ответом. Теперь позови народ их форума C++, пусть тебе оценок наставят за внимательность!
I>А какой смысл формулировать правила, которые нужно понимать не так, как они написаны, а как-то иначе?
Очевидно нужно, иначе как объяснить, что правило "если значения, переданные в качестве параметров конструктора не хранятся потом в самом объекте, то лучше заменить такой конструктор обычным методом" не рекомендует заменить ни List<T>(Int32), ни List<T>(IEnumerable<T>)? Как слово "значение" в правиле не понимай, по крайней мере один из конструкторов согласно правилу "лучше заменить обычным методом".
Здравствуйте, igna, Вы писали:
_FR>>Параметр этого конструктора — capacity списка. У списка есть такое свойство, как Capacity.
I>А значение Capacity обязано "хранятся потом в самом объекте"? Это ведь дело реализации, можно ведь и пройти список и посчитать.
I>Кроме того, свойство Collection для конструктора List<T>(IEnumerable<T>) у списка есть?
Жаль, нету смайлика с крутящимся у виска пальцем
Продолжать беседу в том же духе смысла не вижу, и вам не желаю.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, samius, Вы писали:
S>>Нужно ли?
I>Очевидно нужно, иначе как объяснить, что правило "если значения, переданные в качестве параметров конструктора не хранятся потом в самом объекте, то лучше заменить такой конструктор обычным методом" не рекомендует заменить ни List<T>(Int32), ни List<T>(IEnumerable<T>)? Как слово "значение" в правиле не понимай, по крайней мере один из конструкторов согласно правилу "лучше заменить обычным методом".
Теперь я вижу претензии еще и к фразе "хранятся потом в самом объекте".
Добро, заменяй обычными методами
P>class Ticket
P>{
P> public Ticket(int id) {}
P> public static Ticket InitTicket(int id) {}
P> public static explicit operator Ticket(int id) {}
P>}
P>
P>каковы доводы в пользу того или иного метода инициализации экземпляра объекта по ID?
Метод номер 3 отметается сразу — это ужас какой-то. Причем такие финты я вижу уже третий раз за последние пару месяцев. Мне это кажется странным, так как имхо даже при желании сложно так умудриться извратиться. Перегрузка операторов приведения не должна использоваться в таком контексте — такое поведение совершенно неочевидно для программиста. Операторы приведения должны перегружаться тогда, когда приведение и его результат ожидаемы для программиста и оператор приведения перегружается для удобства. Злоупотреблять перегрузкой операторов не нужно.
Теперь по поводу пунктов 1 и 2.
Начну с того, что основным принятым способом создания объектов является конструктор, т.е. в общем случае следует предпочитать конструктор. Использование фабричного метода вместо конструктора должно быть обосновано какими-либо причинами, среди которых могут быть:
— Необходимость бОльшего контроля над созданием объекта, чем это позволяет конструктор. Основной пример — кеширование, т.е. если с заданными параметрами уже находится в кеше — возвращаем его из кеша. Другой пример — когда тип возвращаемого объекта определяется в рантайме, в зависимости от параметров переданных фабричному методу.
— Необходимость дать специальное имя фабричному методу для того, чтобы было более понятно, как будет происходить конструирование объекта.
— Фабричный метод предпочитают конструктору, когда объект создается на основе парсинга/конвертации, примеры из .NET — DateTime.Parse(string), IPAddress.Parse(string).
Здравствуйте, MozgC, Вы писали:
MC>Теперь по поводу пунктов 1 и 2. MC>Начну с того, что основным принятым способом создания объектов является конструктор, т.е. в общем случае следует предпочитать конструктор. Использование фабричного метода вместо конструктора должно быть обосновано какими-либо причинами, среди которых могут быть:
Согласен, но с оговоркой о том что
1) фабричный метод не может быть использован в качестве constructor-initializer производными классами
2) конструктор не может быть использован при конструировании делегата. Но это как-раз не проблема, можно конструктор обернуть методом, в том числе анонимным.
Здравствуйте, igna, Вы писали:
I>>>Кроме того, свойство Collection для конструктора List<T>(IEnumerable<T>) у списка есть? S>>Ну а причем тут свойство Collection? Список хранит набор переданных значений. Что именно не нравится?
I>"В качестве параметра" был передан IEnumerable<T>, конструктор использует его, чтобы получить "набор переданных значений", но не хранит сам параметр. А то так ведь и имя файла можно конструктору передать, откуда значения читать. Или это правилом разрешено?
Здравствуйте, Ikemefula, Вы писали:
I>Судя по тому, что ты предложил в ответ на высказывание Фреда, где то у тебя есть пробел, потому задаю вопросы с целью обнаружить оный пробел.
Ну давай посмотрим на твой пробел. Нужно ли какие-либо из приведенных ниже конструкторов заменить на статические методы согласно правилу Фреда, и если да, то какие?:
Здравствуйте, igna, Вы писали:
I>>Судя по тому, что ты предложил в ответ на высказывание Фреда, где то у тебя есть пробел, потому задаю вопросы с целью обнаружить оный пробел.
I>Ну давай посмотрим на твой пробел. Нужно ли какие-либо из приведенных ниже конструкторов заменить на статические методы согласно правилу Фреда, и если да, то какие?:
Вижу, ты будешь долго бегать от вопросов
Повторю, на всякий — какова на твой взгляд семантика интерфейса IEnumerable ?
I>А если нет, то приведи пример конструктора, который следовало бы заменить статическим методом.
О чем я и говорил — двух последних конструкторов не должно быть, более того, и статического метода тоже быть не должно
Второй конструкто, если n это capasity то вполне нормально. Если это именно заполнение коллекции пустыми строками, то этого конструктора опять же быть не должно, ровно как и статического метода.
Остается первый конструктор к которому ты не написал комментария, если он такой же, как и List<string>(IEnumerable<string>) то все в порядке.
А если в первом коснтрукторе у тебя передаются пути к файлу и локаторы для ридеров, то ясное дело, и этого конструктора быть не должно как и статического метода.
I>О чем я и говорил — двух последних конструкторов не должно быть, более того, и статического метода тоже быть не должно
А что долнжно быть вместо них?
I>Второй конструкто, если n это capasity то вполне нормально. Если это именно заполнение коллекции пустыми строками, то этого конструктора опять же быть не должно, ровно как и статического метода.
А если "n это capasity" и "это именно заполнение коллекции пустыми строками"?
I>Остается первый конструктор к которому ты не написал комментария, если он такой же, как и List<string>(IEnumerable<string>) то все в порядке.
Он делает то же что и последние два с поправкой на то, откуда берутся строки.
Здравствуйте, igna, Вы писали:
I>>О чем я и говорил — двух последних конструкторов не должно быть, более того, и статического метода тоже быть не должно
I>А что долнжно быть вместо них?
Ничего.
I>>Остается первый конструктор к которому ты не написал комментария, если он такой же, как и List<string>(IEnumerable<string>) то все в порядке.
I>Он делает то же что и последние два с поправкой на то, откуда берутся строки.
Ни в коем случае. Раскрой свое понимание семантики IEnumerable ?
Здравствуйте, Ikemefula, Вы писали:
I>Раскрой свое понимание семантики IEnumerable ?
Не понимаю вопроса. Точнее понимаю его только в том смысле, в котором его могли бы задать на экзамене.
И кстати, ты не ответил на то, имеет ли право на существование конструктор MyStringCollection(int n), если "n это capasity" и "это именно заполнение коллекции пустыми строками".
Здравствуйте, igna, Вы писали:
I>>Раскрой свое понимание семантики IEnumerable ?
I>Не понимаю вопроса. Точнее понимаю его только в том смысле, в котором его могли бы задать на экзамене.
Все ты понимаешь. Потому и вилять начал, и вопросы встречные задавать, лишь бы не отвечать на него.
I>И кстати, ты не ответил на то, имеет ли право на существование конструктор MyStringCollection(int n), если "n это capasity" и "это именно заполнение коллекции пустыми строками".
Цитирую себя:
"Второй конструкто, если n это capasity то вполне нормально. Если это именно заполнение коллекции пустыми строками, то этого конструктора опять же быть не должно, ровно как и статического метода."
Если бы ты пробовал прочесть, что тебе пишут, было бы гораздо лучше.
Здравствуйте, Ikemefula, Вы писали:
I>Все ты понимаешь. Потому и вилять начал, и вопросы встречные задавать, лишь бы не отвечать на него.
Возможно ты считаешь, что я просто стою на своем невзирая. Это не так. Более того, был бы уверен в своей правоте, в дискуссию бы не ввязывался. Может быть ты сам приведешь правильный ответ на свой вопрос?
Еще интереснее было бы посмотреть на два по возможности близких метода, один из которых согласно правилу Фреда должен быть конструктором, второй — статическим методом.
Здравствуйте, igna, Вы писали:
I>>Все ты понимаешь. Потому и вилять начал, и вопросы встречные задавать, лишь бы не отвечать на него.
I>Возможно ты считаешь, что я просто стою на своем невзирая. Это не так. Более того, был бы уверен в своей правоте, в дискуссию бы не ввязывался. Может быть ты сам приведешь правильный ответ на свой вопрос?
Быть уверенным — мало. Надо быть готовым объяснить оппоненту свою позицию так, что бы она была бы ясна. Суть твоих претензий не понятна всем трём твоим собеседникам в этом топике
А значение Capacity обязано "хранятся потом в самом объекте"? Это ведь дело реализации, можно ведь и пройти список и посчитать.
С моей точки зрения — бессмысленный набор слов: Мыже говорим о конкретной реализации (классе List<>) — интерфейс получить интересующую нас информацию позволяет, что я показал, а "напрямую" там хранится заданное значение или может быть вычисленно косвенно — дело сто тридцать седьмое. Если у тебя есть сообоажения относительно того, почему я в данном рункте не прав — велкам, высказывай свои соображения, но не "реплики из зала". А не то снова будешь принят за троля. Пока что ни одного соображения ты тут не высказал.
I>Еще интереснее было бы посмотреть на два по возможности близких метода, один из которых согласно правилу Фреда должен быть конструктором, второй — статическим методом.
Если бы вёл себя не как троль, а высказал бы чётко свою мысль, было бы проще. Пока же совершенно не понятно с чем именно ты "не согласен
не попадает под действие "правила", ибо параметров ему не дадено.
Конструктор
List<T>(IEnumerable<T>)
под действие правила попадает, и "правило" однозначно позволяет ответить на вопрос "Какие из них следовало бы заменить обычными методами?". Но надо прочесть его ("правило") внимательно или доступно объяснить, что в формулировке тебя смущает и не позволяет найти ответ.
Здравствуйте, igna, Вы писали:
_FR>>Параметр этого конструктора — capacity списка. У списка есть такое свойство, как Capacity.
I>А значение Capacity обязано "хранятся потом в самом объекте"? Это ведь дело реализации, можно ведь и пройти список и посчитать.
Capacity — это не Length.
Как можно при создании списка зарезервировать сразу кусок памяти нужного размера, не передавая этот самый размер в конструктор — мне лично не ясно совершенно.
И таки да, в результате оно хранится в самом объекте (уж как минимум в виде вычислимого значения текущего размера зарезервированного блока памяти, каковой хранится — сюрприз — внутри объекта List)
Здравствуйте, igna, Вы писали:
I>>Все ты понимаешь. Потому и вилять начал, и вопросы встречные задавать, лишь бы не отвечать на него.
I>Возможно ты считаешь, что я просто стою на своем невзирая. Это не так. Более того, был бы уверен в своей правоте, в дискуссию бы не ввязывался.
Никто и не отрицает, что у тебя есть мнение. Все дело в том, как ты ведешь беседу.
Когда я спросил про семантику, ты дал ответ ссылкой, что подразумевает, что обозначеный вопрос ты понял.
Когда же я уточнил, что спрашиваю твое понимание вопроса, ты сказал что де вопрос не понят.
Т.е. как просветить меня, так все ясно, а как показать свое понимание, так вопрос не понят.
Стало быть осознанно или нет ты не желаешь давать ответ.
I>Еще интереснее было бы посмотреть на два по возможности близких метода, один из которых согласно правилу Фреда должен быть конструктором, второй — статическим методом.
И ежу ясно, что встречные вопросы означают, что ответа на вопрос не будет. Посему пока я не увижу ответа на свой вопрос не задавай вопросов, ибо я и так дал тебе аванс отвечая про MyStringCollection.
Хорошо, я понял твою позицию по поводу этих трех конструкторов, но не понял почему твое правило запрещает конструктор MyStringCollection(TextReader) (читающий построчно). Не мог бы ты ответить на вопрос, можно ли заменить его статическим методом? А если нет, то чем, методом принимающим TextReader и возвращающим IEnumerable<string>?
Здравствуйте, igna, Вы писали:
I>Хорошо, я понял твою позицию по поводу этих трех конструкторов, но не понял почему твое правило запрещает конструктор MyStringCollection(TextReader) (читающий построчно). Не мог бы ты ответить на вопрос, можно ли заменить его статическим методом? А если нет, то чем, методом принимающим TextReader и возвращающим IEnumerable<string>?
Между IEnumerable и TextReader — громадная разница. IEnumerable<T> является частью реализации List как и большинства контейнеров данных. Поэтому конструктор List<T>(IEnumerable<T>) является практически аналогом конструктора копирования в С++. TextReader — не является частью реализации List, и ни должен им являться. Соответвенно, в случае если мы реализуем его в классе List, мы нарушим принципы SRP, поскольку введем в контейнер совершенно другую функциональность чтения из файла/стрима. Контейнеры в NET и так благообразием дизайна не блещут.
Не мог бы ты ответить на вопрос, можно ли заменить конструктор MyStringCollection(TextReader) статическим методом? А если нет, то чем, методом принимающим TextReader и возвращающим IEnumerable<string>?
Здравствуйте, _FRED_, Вы писали:
_FR>Ой ли? И какова же моя позиция "по поводу этих трех конструкторов" на твой взгляд?
Что твое правило их не запрещает.
Не мог бы ты ответить на вопрос, можно ли заменить конструктор MyStringCollection(TextReader) статическим методом? А если нет, то чем, методом принимающим TextReader и возвращающим IEnumerable<string>?
Здравствуйте, igna, Вы писали:
_FR>>Ой ли? И какова же моя позиция "по поводу этих трех конструкторов" на твой взгляд?
I>Что твое правило их не запрещает.
А по какой причине? Я не просто так спрашиваю, ибо это действительно важно, что бы мы все понимали, о чём ведём речь.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, igna, Вы писали:
I>Не мог бы ты ответить на вопрос, можно ли заменить конструктор MyStringCollection(TextReader) статическим методом? А если нет, то чем, методом принимающим TextReader и возвращающим IEnumerable<string>?
1. А это уже зависит от цели. В случае, если ты даешь много гарантий, что это сильноповторяющаяся процедура, и формат файла всегда соответсвует формату List, например перенос строки означает начало нового элемента, то почему бы и нет. Хотя такие идеи весьма сильно не нравятся, поскольку ломают инкапсуляцию контейнера и ограничивают гибкость. Ежели не повторяющаяся, то это вполне элемент сценария, и может быть частью класса отвечающего за сценарий. Ежли, даже гипотетически, формат может меняться, или может происходить дообработка данных — то раздельный класс. Но — ни в коем случае конструктор.
2. Между IEnumerable<T> и IList<T> — совершенно разная семантика. Ты решил бы что именно тебе нужно.
Здравствуйте, GlebZ, Вы писали:
GZ>1. А это уже зависит от цели. В случае, если ты даешь много гарантий, что это сильноповторяющаяся процедура, и формат файла всегда соответсвует формату List, например перенос строки означает начало нового элемента, то почему бы и нет. Хотя такие идеи весьма сильно не нравятся, поскольку ломают инкапсуляцию контейнера и ограничивают гибкость. Ежели не повторяющаяся, то это вполне элемент сценария, и может быть частью класса отвечающего за сценарий. Ежли, даже гипотетически, формат может меняться, или может происходить дообработка данных — то раздельный класс. Но — ни в коем случае конструктор.
Понятно. А конструктор MyStringCollection(string[]) правило Фреда не запрещает?
GZ>2. Между IEnumerable<T> и IList<T> — совершенно разная семантика. Ты решил бы что именно тебе нужно.
Да, я понимаю, что семантика между ними это две большие разницы. Но во-первых, IList<T> в примерах по-моему еще не появлялся, а во-вторых, не хотелось бы, чтобы обсуждение семантик между интефейсами увело нас в куда-нибудь не туда.
Здравствуйте, igna, Вы писали:
_FR>>А по какой причине? Я не просто так спрашиваю, ибо это действительно важно, что бы мы все понимали, о чём ведём речь.
I>Я не готов отвечать,
I>сначала хочу удостоверится, что понял правило, предлагаемое тобой, верно; поэтому и спрашиваю, как оно будет работать в конкретных случаях.
Ага, "отвечать" "не готов", а уже и оценкой и словом не раз выразил несогласие со мной, а так же не постеснялся назвать меня "нервным" Нет, так разговор не ведётся, извините.
Лучше объясни (если действительно "хочешь удостоверится"), как понял: желательно на примере, который сам и выдумал — с конструкторами List<T>.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>не постеснялся назвать меня "нервным"
Вот ты на что обиделся. Так ведь ты меня тоже вроде чем-то там назвал (я собственно даже слова того толком не знаю).
_FR>Лучше объясни (если действительно "хочешь удостоверится"), как понял
Так не могу, не понял еще; оно (твое правило) вообще мне кажется недостаточно четким. То есть предполагаю, что если составить подборку из десяти различных конструкторов и дать тебе и тем троим, кто понял твое правило и обрадовался, определить, какие из конструкторов удовлетворяют твоему правилу, какие — нет, то получим 4 несовпадающие ответа. Но возможно я ошибаюсь.
Вот тебе-то что стоит ответить, запрещает ли твое правило конструктор MyStringCollection(string[])? Ведь 2 или 3 буквы всего, и после трех-четырех вопросов все с тобой будет ясно.
Здравствуйте, igna, Вы писали:
_FR>>Лучше объясни (если действительно "хочешь удостоверится"), как понял
I>Так не могу, не понял еще; оно (твое правило) вообще мне кажется недостаточно четким. То есть предполагаю, что если составить подборку из десяти различных конструкторов и дать тебе и тем троим, кто понял твое правило и обрадовался, определить, какие из конструкторов удовлетворяют твоему правилу, какие — нет, то получим 4 несовпадающие ответа. Но возможно я ошибаюсь.
I>Вот тебе-то что стоит ответить, запрещает ли твое правило конструктор MyStringCollection(string[])? Ведь 2 или 3 буквы всего, и после трех-четырех вопросов все с тобой будет ясно.
В том-то и дело: ответить не сложно, но это вызовет кучу новых вопросов. Это не продуктивно.
Продуктивно было бы как-то так: ты задаёшь вопрос, требующий ответа "Да" или "Нет". Далее думаешь (и говоришь здесь): если ответ "Да", то "мне непонятно следующее…" или "я вижу противоречие с тем-то", а если ответ "Нет", то "как это соответствует тому-то"?
Вот расскажи, что тебя будет смущать (что будет не понятно или какое противоречие в твоих логический выкладках возникнет) в случае положительного ответа на вопрос "запрещает ли правило конструктор MyStringCollection(string[])" и в случае отрицательного. Без такой формулировки с твоей стороны я никогда не смогу дать удовлетворительного для тебя ответа (если мне не повезёт вдруг угадать, но я не гадалка), поэтому "перетягивания" всячески избегаю и избегать буду впредь.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Вот расскажи, что тебя будет смущать (что будет не понятно или какое противоречие в твоих логический выкладках возникнет) в случае положительного ответа на вопрос "запрещает ли правило конструктор MyStringCollection(string[])" и в случае отрицательного. Без такой формулировки с твоей стороны я никогда не смогу дать удовлетворительного для тебя ответа (если мне не повезёт вдруг угадать, но я не гадалка), поэтому "перетягивания" всячески избегаю и избегать буду впредь.
То есть ответ будет зависить от аргументов, которые я должен выложить заранее для обоих случаев. Почти как покер, когда один видит карты другого, а тот его нет. Ну и ладно, можно и так.
Если твое правило запрещает конструктор MyStringCollection(string[]), то я не понимаю, почему оно разрешает MyStringCollection(IEnumerable<string>), если же наоборот, то неясно, почему запрещен MyStringCollection(TextReader).
Здравствуйте, GlebZ, Вы писали:
GZ>Нет. В честь чего?
Не знаю. Вот правило:
Семантика такая: конструктор — это метод, в который передаётся некоторое "начальное" состояние объекта
То, что это правило разрешает MyStringCollection(string[]), но запрещает MyStringCollection(TextReader), на мой взгляд неочевидно. К примеру вполне логично, что то самое "состояние объекта" было сохранено в файле и теперь читается из него при создании экземпляра MyStringCollection.
Здравствуйте, igna, Вы писали:
I>Если твое правило запрещает конструктор MyStringCollection(string[]), то я не понимаю, почему оно разрешает MyStringCollection(IEnumerable<string>), если же наоборот, то неясно, почему запрещен MyStringCollection(TextReader).
Повторюсь: с чего ты взял, что "оно разрешает MyStringCollection(IEnumerable<string>)"? Я уже говорил немного выше, что это — ключевой момент.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, igna, Вы писали:
I>Не знаю. Вот правило:
I>
I>Семантика такая: конструктор — это метод, в который передаётся некоторое "начальное" состояние объекта
I>То, что это правило разрешает MyStringCollection(string[]), но запрещает MyStringCollection(TextReader), на мой взгляд неочевидно. К примеру вполне логично, что то самое "состояние объекта" было сохранено в файле и теперь читается из него при создании экземпляра MyStringCollection.
Есть набор типов встроенных в среду и компилятор. Нам в голову ни придет что надо писать логику сложения для int или double. Она уже реализована компилятором. string[] или IEnumerable<T> — не сильно отличается от int. В отличие от TextReader, который требует отдельной логики доступа.
Здравствуйте, GlebZ, Вы писали:
GZ>Есть набор типов встроенных в среду и компилятор. Нам в голову ни придет что надо писать логику сложения для int или double. Она уже реализована компилятором. string[] или IEnumerable<T> — не сильно отличается от int. В отличие от TextReader, который требует отдельной логики доступа.
Логика у него есть и называется метод GetLine. То есть TextReader фактически имплементирует паттерн Iterator. Но дело даже не в этом, а в том, что аргументация твоя есть нечто дополнительное к правилу Фреда.
Я прошу тебя высказать твоё собственное мнение. Почему ты даёшь ссылку на пост другого человека?
Ответь пожалуйста на мой вопрос чётко и прямо. Если не можешь — значит или не хочешь или недостаточно подумал.
В любом из этих двух случаев продолжать бессмысленно.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Я прошу тебя высказать твоё собственное мнение. Почему ты даёшь ссылку на пост другого человека? _FR>Ответь пожалуйста на мой вопрос чётко и прямо. Если не можешь — значит или не хочешь или недостаточно подумал.
Хорошо, господин учитель.
IEnumerable<string> полностью описывает состояние объекта, поэтому конструктор MyStringCollection(IEnumerable<string>) разрешен правилом Фреда.
Здравствуйте, igna, Вы писали:
_FR>>Я прошу тебя высказать твоё собственное мнение. Почему ты даёшь ссылку на пост другого человека? _FR>>Ответь пожалуйста на мой вопрос чётко и прямо. Если не можешь — значит или не хочешь или недостаточно подумал.
I>Хорошо, господин учитель.
Давай всё-таки без подхолимажа и прочей гомосятины, ладно? Это называется переходом на личности.
I>IEnumerable<string> полностью описывает состояние объекта,
"состояние" какого "объекта"? Допустим:
IEnumerable<string> items = GetItems();
List<string> list = new List<string>(items);
так "состояние" какого "объекта" здесь "полностью" описывается с помощью "IEnumerable<string>"? Первого — возможно, но при чём здесь состояние этого объекта? Второго — не правда. Состояние List<string> не описывается полностью параметром конструктора, принимающего перечислииель.
I>поэтому конструктор MyStringCollection(IEnumerable<string>) разрешен правилом Фреда.
Покажи мне место в том, что ты называешь "правилом Фреда", где бы говорилось хоть что-нибудь о то, что "полностью описывает состояние объекта" Нигде я ничего подобного не говорил. Всё-таки ты всё ещё тролишь, ибо перевираешь слова собеседника и вместо чётких формулировок выдаёшь оскорбительные ("Хорошо, господин учитель. ") и расплывчатые. Посему вместо ответа на свои вопросы ты получаешь всё новые вопросы :о)) "Так держать".
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>"состояние" какого "объекта"?
Ну значит я неправ.
_FR>Покажи мне место в том, что ты называешь "правилом Фреда", где бы говорилось хоть что-нибудь о то, что "полностью описывает состояние объекта" Нигде я ничего подобного не говорил.
Значит я опять неправ.
Значит неверно понял правило. Честно говоря не знаю, что еще написать, чтобы ты не принял мои слова за стеб и ответил все же на вопрос, допускает ли твое правило MyStringCollection(string[]) или нет. Может это можно непублично как-нибудь выяснить? Я уже готов дать свой адрес, хоть и стращают всякие разные.
Здравствуйте, igna, Вы писали:
_FR>>"состояние" какого "объекта"?
I>Ну значит я неправ.
Почему и в чём?
_FR>>Покажи мне место в том, что ты называешь "правилом Фреда", где бы говорилось хоть что-нибудь о то, что "полностью описывает состояние объекта" Нигде я ничего подобного не говорил.
I>Значит я опять неправ. I>Значит неверно понял правило.
Отлично.
I>допускает ли твое правило MyStringCollection(string[]) или нет.
Допускает или нет — зависит не от типов параметров, а от того, как переданный массив используется. По одному объявлению ответить на вопрос невозможно.
Давай с классом List<> разберёмся (поскольку его реализация нам известна), вернее с его конструктором List<>(IEnumerable<>). Я бы не добавлял такой [открытый] конструктор в класс, а конструирование списка из IEnumerable<> возложил бы на статический метод. Потому что такой вот код:
void Test(MyBusinessEntitiesCollection<MyEntity> items) {
var list = new List<MyEntity>(items);
var collection = new Collection<MyEntity>(items);
}
мне не нравится — через конструктор не передаётся связь между аргументом и созданным объектом. В первом случае происходит копирование, а во-втором — создаётся обёртка-декоратор.
Вот так вот, имхо, было бы гораздо понятнее:
void Test(MyBusinessEntitiesCollection<MyEntity> items) {
var list1 = items.ToList(); // "To" - значит скопировалиvar list2 = List.Create(items);
var collection = new Collection<MyEntity>(items);
var collection2 = items.AsMyDecorator(); // "As" - обернули
}
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Давай с классом List<> разберёмся (поскольку его реализация нам известна), вернее с его конструктором List<>(IEnumerable<>). Я бы не добавлял такой [открытый] конструктор в класс, а конструирование списка из IEnumerable<> возложил бы на статический метод.
Вот. Но кое-кто из согласных с твоим правилом твоего мнения по поводу этого конкретного конструктора не разделяет:
Остается первый конструктор к которому ты не написал комментария, если он такой же, как и List<string>(IEnumerable<string>) то все в порядке.
Здравствуйте, fmiracle, Вы писали:
F>Как можно при создании списка зарезервировать сразу кусок памяти нужного размера, не передавая этот самый размер в конструктор — мне лично не ясно совершенно.
Здравствуйте, _FRED_, Вы писали:
_FR>ИМХО, очень сомнительный вывод. Впрочем, даже в этом топике не в первый раз, так что тролль себе дальше.
А зачем? Пока была вероятность, что правило Фреда имеет смысл, я пытался разобраться. А теперь все ясно. Но спасибо за разъяснения, другие просто убежали, почувствовав понятно что.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, samius, Вы писали:
S>>Да и AFAIR в msdn попадались примеры с наследованием от него.
I>Это было бы интересно посмотреть. Вдруг кто знает, где.
На счет msdn не уверен, но в рефлекторе примеры найти не сложно.
Здравствуйте, _FRED_, Вы писали:
_FR>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает).
То, что "конструктор с capacity делает чего такого", не обязывает его быть открытым.
Здравствуйте, igna, Вы писали:
F>>Как можно при создании списка зарезервировать сразу кусок памяти нужного размера, не передавая этот самый размер в конструктор — мне лично не ясно совершенно. I>Это верно, но конструктор-то может быть закрытым.
Не понятно к чему это.
Конструктор с указываемой Capacity интересен именно как открытый.
Здравствуйте, igna, Вы писали:
_FR>>Нет, наследование здесь не при чём. Дело просто в том, что этот конструктор не делает ничего такого, что нельзя было бы сделать без него (а конструктор с capacity делает). I>То, что "конструктор с capacity делает чего такого", не обязывает его быть открытым.
Но желание применить возможности, которые дает конструктор с capacity (а именно, оптимизация быстродействия), обязывает его быть открытым.
Здравствуйте, fmiracle, Вы писали:
F>Конструктор с указываемой Capacity интересен именно как открытый.
Он может быть закрытый и вызываться открытым статическим методом. Такая комбинация закрытого конструктора и открытого статического метода популярна, поэтому я сначала ответил кратко, без подробностей.
Здравствуйте, _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?
Здравствуйте, 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.
Здравствуйте, igna, Вы писали:
F>>Конструктор с указываемой Capacity интересен именно как открытый. I>Он может быть закрытый и вызываться открытым статическим методом. Такая комбинация закрытого конструктора и открытого статического метода популярна, поэтому я сначала ответил кратко, без подробностей.
Если этот статический метод вызывает ровно закрытый конструктор с теми же аргументами, что и у данного метода, то, совершенно очевидно, что данный статический метод — излишен.
Здравствуйте, fmiracle, Вы писали:
F>Если этот статический метод вызывает ровно закрытый конструктор с теми же аргументами, что и у данного метода, то, совершенно очевидно, что данный статический метод — излишен.
Нет, боюсь примотаешься к какому слову — допишу еще немного — "и этот метод не делает ничего больше, кроме как вызов этого самого конструктора, который с теми же самыми аргументами".
Здравствуйте, fmiracle, Вы писали:
F>"и этот метод не делает ничего больше, кроме как вызов этого самого конструктора, который с теми же самыми аргументами".
То есть все же бывают случаи, когда конструктор с указываемой Capacity интересен не только как открытый.
Здравствуйте, 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.
Здравствуйте, fmiracle, Вы писали:
F>Но желание применить возможности, которые дает конструктор с capacity (а именно, оптимизация быстродействия), обязывает его быть открытым.
Здравствуйте, _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 делает лишние копирования.
Здравствуйте, samius, Вы писали:
S>Ну вот, лишнего перераспределения избежать удалось, но эффективное копирование может организовать лишь конструктор List<T>(IEnumerable<T>).
А что в этом копировании неэффективного?
S>На больших размерах коллекций это сыграет куда сильнее, чем лишнее перераспределение.
Что ты называешь "больших"? Будет ли при указанных размерах вообще эффективным использование List<>? Ибо добавление одного элемента в "болшой" список может вызвать копирование имеющегося буфера. Поиск (ввиду линейной сложности, то есть полного перебора) практически бессмысленен.
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _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) может оказаться медленнее.
Здравствуйте, igna, Вы писали:
_FR>>ИМХО, очень сомнительный вывод. Впрочем, даже в этом топике не в первый раз, так что тролль себе дальше.
I>А зачем? Пока была вероятность, что правило Фреда имеет смысл, я пытался разобраться. А теперь все ясно. Но спасибо за разъяснения, другие просто убежали, почувствовав понятно что.
Здравствуйте, igna, Вы писали:
F>>"и этот метод не делает ничего больше, кроме как вызов этого самого конструктора, который с теми же самыми аргументами". I>То есть все же бывают случаи, когда конструктор с указываемой Capacity интересен не только как открытый.
Это к чему?
Бывают случаи, когда конструктор с указываемой Capacity интересен как открытый. Внешний вызов требует лишнего пересоздания внутреннего буффера.
И при этом ничем тот же функционал не заменишь, кроме просто открытого метода, которая не делает ничего, помимо вызова этого конструктора. Так зачем ее городить, а не просто сделать открытый конструктор?
Здравствуйте, fmiracle, Вы писали:
F>И при этом ничем тот же функционал не заменишь, кроме просто открытого метода, которая не делает ничего, помимо вызова этого конструктора. Так зачем ее городить, а не просто сделать открытый конструктор?
Согласен. Но вряд ли это тот случай, когда "конструктор — это метод, в который передаётся некоторое начальное состояние объекта". Capacity это не состояние, а подсказка, hint.
Здравствуйте, igna, Вы писали:
I>Согласен. Но вряд ли это тот случай, когда "конструктор — это метод, в который передаётся некоторое начальное состояние объекта". Capacity это не состояние, а подсказка, hint.
Хм? Этот параметр именно определяет какое будет внутреннее состояние (размер выделенного внутреннего массива).