Здравствуйте, Gattaka, Вы писали:
G>Ну так есть ведь флажок beforefieldinit. Который сказывается на производительности. Т.е. достаточно вам только добавить статический конструктор к типу, как получаете просадку по производительности в неожиданном месте. Плюс есть соблазн работать из статического метода с другими полями, а не только создавать экземпляр. Нужно синхронизировать и т.п. Вобщем решение со статическими методами всегда выглядит не очень здорово. Лично я стараюсь избегать статических методов.
Это очень смелое утверждение. Андрей Акиньшин недавно показал, когда это может произойти, но я не помню как-то кейсов, когда проверка статического конструктора *настолько* влияла на производительность end-2-end приложения, чтобы нужно было менять дизайн, чтобы обойти это дело.
И да, "достаточно" закоммитить Thread.Sleep в 73-х местах и любое приложение будет тормозным. Будет проблема, будет профилирование и будет решение. Сильно много future proofing-а в предыдущем абзаце.
и готов повторить: статические методы — это не хорошо или плохо. Статические методы с побочными эффектами — чистое зло, а чистые статические методы — это просто прекрасно, ибо их проще читать, тестить и реюзать. И ООП embrace-ит это не хуже ФП, пусть и ничего не гарантирует. Если же именно этот факт кого-то пугает (что ведь можно что-то поменять, и все сломать), то как тогда вообще жить? ведь кто-то может получить доступ через рефлексию к типу вашего массива и сменить его тип во время исполнения? Все, что угодно можно использовать неправильно и вопрос лишь в том, насколько это легко сделать? С моей колокольни использовать неправильно контейнер легче, чем использовать неверно статический метод, ибо первое — это один большой стейт и god-object, а второй — это примитив из которого строится функциональность приложения.
Здравствуйте, _NN_, Вы писали: _NN>У второго варианта удобнее использование, ведь X,Y будут скрыты от глаз, зато первый вариант не создает ненужного наследования.
Как правило, если у вас возникает вот такой вот "популярный алиас", то недалеко и то время, когда он станет отличаться от от предка.
Поэтому введение алиаса типа NameValueCollection: Dictionary<string, string> оправдано.
Дело не в том, скрыты ли от глаз X и Y. А в том, как вы выражаете требования — если у вас какой-то метод принимает Dictionary<string, string>, то он не вправе ожидать, скажем, case-insensitive сравнения ключей.
Даже если вы сделаете фабрику NameValueCollection с методом Create(), который верно проинициализирует предка, то нет способа потребовать в аргументах именно такой объект.
А как только вы объявили свой NameValueCollection, то тут же получаете возможность явно требовать именно его и полагаться на консистентную инициализацию (а в будущем — и на какие-то дополнительные инварианты, которые вы обеспечите перекрытием унаследованных методов и другим нетривиальным кодом).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, _NN_, Вы писали: _NN>>У второго варианта удобнее использование, ведь X,Y будут скрыты от глаз, зато первый вариант не создает ненужного наследования. S>Как правило, если у вас возникает вот такой вот "популярный алиас", то недалеко и то время, когда он станет отличаться от от предка. S>Поэтому введение алиаса типа NameValueCollection: Dictionary<string, string> оправдано. S>Дело не в том, скрыты ли от глаз X и Y. А в том, как вы выражаете требования — если у вас какой-то метод принимает Dictionary<string, string>, то он не вправе ожидать, скажем, case-insensitive сравнения ключей. S>Даже если вы сделаете фабрику NameValueCollection с методом Create(), который верно проинициализирует предка, то нет способа потребовать в аргументах именно такой объект. S>А как только вы объявили свой NameValueCollection, то тут же получаете возможность явно требовать именно его и полагаться на консистентную инициализацию (а в будущем — и на какие-то дополнительные инварианты, которые вы обеспечите перекрытием унаследованных методов и другим нетривиальным кодом).
Основная странность здесь в стремлении скрыть X и Y. Это как бы намекает, что зря сделали дженерик если возникает такое желание скрыть.
Здравствуйте, Gattaka, Вы писали:
G>Основная странность здесь в стремлении скрыть X и Y. Это как бы намекает, что зря сделали дженерик если возникает такое желание скрыть.
Не уверен, что изначальная формулировка верна. Прямо "скрыть скрыть" всё равно не получится — скорее всего, речь о том, чтобы а) убрать с видного места (Кого там интересует, что мы наследуемся от IReadWriteOperations<T>, где T — это CustomerOperationsAbstract<Arithmetic<BigInt>, RetryLogic.ExponentialRetryLogic>>) и б) прекатить обязать всё это выписывать при каждом использовании.
Так-то никаких проблем нету — очень часто "частные специфичные" вещи очень похожи (до неотличимости) на удобный дженерик.
Ну вот из простейшего — целочисленный Random изоморфен IEnumerable<int>.
Но это же не означает, что IEnumerable<int> зря объявлен дженериком.
Тем не менее, если я пишу какой-то код, который может работать с разными генераторами ПСЧ, то лучше его типом параметра всё же взять IRandomSequenceProvider, даже если этот интерфейс ничего не добавляет к базовому для него IEnumerable<int>. Просто из соображений коммуникации — чтобы избежать искушения скормить в мой крипто-модуль формально подходящий параметр вроде {0,}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.