Непонятки с EF
Играюсь я тут дома с прогой. НЕТ 8.0
Простой поиск
_dbContext.Users.FirstOrDefault(u => u.Email == email);
Выдаёт непонятную ошибку.
"
Microsoft.Data.SqlClient.SqlException
Invalid column name 'UserId'.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
...
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData()
...
"
При этом юнит тесты с репозиторием и реальной базой работают без проблем. (И с тем же db Context классом)
А вот интеграционный тест выдает уже ошибку, правда сделал на уровень выше с DI и инициализацией базы как в приложении.
Какие будут идеи?
как называется колонка в БД?
Есть ли для класса User класс конфигурации для EF или конфигурация сделана в виде [Column("Id")]?
База генерится так
public sealed class UserConfigurations : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
ConfigureUsersTable(builder);
}
private void ConfigureUsersTable(EntityTypeBuilder<User> builder)
{
builder
.ToTable("Users");
builder
.HasKey(u => u.Id);
builder
.Property(u => u.Id)
//.HasColumnName("UserId")
.ValueGeneratedNever();
//.HasConversion(
// id => id.Value,
// value => UserId.Create(value));
...
С этой строкой не работает .HasColumnName("UserId")
Конверсия сделана глобальной - internal class UserIdConverter : ValueConverter
public sealed class User : AggregateRoot<UserId, Guid>
{
...
private User(
UserId id,
Похоже совсем другое. Как заработало, начал данные искать и тут фигвам, они оказались в другой базе. Где как раз имя колонки Id ![]()
Т.е. дело оказалось в строке подключения, где указана другая база?
оказалось в строке подключения, где указана другая база?
в принципе да, но не всё так просто было.
Для запуска в проекте миграции нужен IDesignTimeDbContextFactory со своей строкой подключения в проекте "с базой"
А для запуска приложения используется другая строка подключения, обе строки должны быть идентичны. /Как их брать их одного места пока не придумал
/
Поэтому база создавалась в одном месте и юнит тесты дергали ее /для тестов тоже своя строка подключения/, а вот старт приложения или интеграционного теста пользовал другую строку соединения.
и юнит тесты дергали ее /для тестов тоже своя строка подключения/,
Глаз зацепился. Как только тест начинает лезть в БД это уже не юнит тест, а интеграционный.
Как только тест начинает лезть в БД это уже не юнит тест, а интеграционный
тут несколько пунктов:
1. Мокать базу смысла не вижу. Обычно база в памяти, не фонтан, но некоторые ошибки можно найти
2. Именно в данном случае, специально использовал реальную базу для дополнительной проверки в чем может быть проблема.
3. Интеграционный тест тоже есть, но он не на уровне репозитория, а "выше"
Хотя сейчас больше интересует другой вопрос как отмапить ссылки на агрегаты по ИД, если ИД - value object
Я не говорю, что такие тесты не надо делать. Просто уточнил терминологию. Дверь надо называть дверью. Тест, работающий с базой (даже если в памяти) - не юнит тест, а интеграционный.
Дверь надо называть дверью
По теории вполне возможно. Но если на практике она долгое время называлась дыркой и выглядит как дырка, то никто не захочет называть это дверью
Разве в проспекте можно написать - дверь в загадочное подземелье...
Если Moq есть, то нефиг называть энто интеграционным тестом.
ну и напрямую ничего про базы нет, кроме side effect.
"Unit tests focus on a single part of a whole application in total isolation, usually, a single class or function. Ideally, the tested component is free of side effects so it is as easy to isolate and test as possible."
"We have learned that, in practice, the isolation property of unit tests may not be enough for some functions. In this case, one solution is to test how parts of the application work together as a whole. This approach is called integration testing.
Unlike unit testing, integration testing considers side effects from the beginning. These side effects may even be desirable."
ну и напрямую ничего про базы нет, кроме side effect.
Мна... Это как? Надо чтобы где-то было написано "юнит тесты не должны использовать базу данных"? И тогда ты поверишь что они действительно это не должны делать?
Не надо искать что-то в "side effects". "...in total isolation, usually, a single class or function".
Если Moq есть, то нефиг называть энто интеграционным тестом.
Неправильно. Во-первых: Mock. Во-вторых: представь, что у тебя три системы (сервиса) А, Б, В. Код из А использует Б и В. Сначала Б, потом В. И ты хочешь проверить интеграцию А с В. Конечно же, ты можешь (и даже должен) замОчить вызов Б. От этого тест не перестал быть интеграционным и стал намного более информативным. Если он сломался - не надо гадать, что у тебя накрылось, Б или В. Ты сразу знаешь что накрылось В.
in total isolation
ладно пойдем от этого... Вот например функция и еще много подобных и посложнее. _dbContext другой класс, значит его нужно чем то заменить. Чем и как?
и как будем после тестировать сам _dbContext? И какой будет толк во всём этом разделении? Не чисто теоретически сервис А и сервис Б, а совершенно практически.
И что изменится если вместо одного названия MyRepo.UnitTest будет другое MyRepo.IntegrationTest? При этом все остальные IntegrationTest используют части "живой системы".
public async Task<Group?> GetMyGroupAsync(UserId ownerId, CancellationToken cancellationToken)
{
Group? group = await _dbContext.Groups
.Include(a => a.Owner)
.Include(a => a.Users)
.Include(a => a.Information)
.FirstOrDefaultAsync(x => x.Owner.Id == ownerId, cancellationToken);
return group;
}
Это очень хороший метод. Для юнит-тестов. Потому что для него юнит-тесты писать не надо. Опа. Он просто "обёртка" вокруг вызова внешней системы. Его надо тестировать интеграционным тестом. Который проверит, что с определённой тестовой БД, в которой есть (например) 10 записей, при поиске с UserId = 123 мы найдём ровно том, что ожидали.
А вот когда мы будем писать юнит-тесты для кода, который вызывает этот метод, мы будем мочить его вызовы. Сможем тестировать код, вызывающий наш гет без БД.
Потому что для него юнит-тесты писать не надо.
Из этого можно сделать вывод, что для всех классов подобного типа не следует писать юнит тесты их просто следует называть интеграционными тестами.
Что меняется от использования другого названия? Тестироваться то будет ОДИН класс, который также написан нами. То есть формально будет юнит тест. Или нужно делать упор на "внешнюю систему", но ведь ее мы не должны тестировать, по умолчанию она работает "правильно".
что с определённой тестовой БД
Этот подход можно пользовать если мы хотим тестировать исключительно Query, а вот с Command будет посложнее, пусть даже база будет в локальном докере.
при поиске с UserId = 123 мы найдём ровно то, что ожидали
Это самое малое что меня будет интересовать в данном случае. А вот загрузится ли полностью владелец или пользователи будет гораздо интереснее.
А если там еще и джойны есть, то есть что проверять.
Статическая база никак не подходит.
А вот когда мы будем писать юнит-тесты для кода, который вызывает этот метод, мы будем мочить его вызовы.
С этим никаких вопросов нет, именно так и делается
нп
А есть какие-то преимущества/недостатки хранения экземпляра dbContext в свойстве класса?
Первое, что приходит на ум, что вот такие вещи будут действовать во всех потоках.
context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.LazyLoadingEnabled = false;
context.Configuration.ProxyCreationEnabled = false;
А есть какие-то преимущества/недостатки хранения экземпляра dbContext в свойстве класса?
Что то не припоминаю подобного вопроса.
А что предлагаете вместо этого?
public class MyRepository
{
private readonly MyDbContext _dbContext;
public MyRepository(MyDbContext dbContext)
{
_dbContext = dbContext;
}
_dbContext
Подчёркивания - давно дурной тон. Как и всякие префиксы b перед булевыми переменными, e перед перечислениями и т.п. IDE давно всё как надо подсвечивает и выдаёт мгновенные всплывающие подсказки по типам переменных и их принадлежности. Зачем захламлять код закорючками, которые помогали, когда IDE были лишь блокнотами с прикрученными компиляторами?
Подчёркивания - давно дурной тон.
А вы вот яйца с какого конца разбиваете? ... Неправильно ![]()
"this." безусловно лучше, особенно когда смотрю сразу целый экран.
альтернатива это
void DeleteUserById(int id)
{
using (var context = new MyDbContext())
context.Users.Remove(x => x.Id == id);
context.SaveChanges();
}
}
В чем преимущества вашего метода?
this нужен лишь в проперти или в конструкторе. Один раз на весь класс. В остальных 10-20 случаях я лучше не буду тянуться до _, тем более, что чтобы в неё попасть, нужно постоянно в неё целиться. Даже если владеешь слепой печатью на английском - всё равно неудобно.
void DeleteUserById(int id)
{
using (var context = new MyDbContext())context.Users.Remove(x => x.Id == id);
context.SaveChanges();
}
А почему SaveChanges не вызывается автоматически при выходе за пределы контекста MyDbContext? Заставляют писать лишнюю, но очевидную строчку кода.
using (var context = new MyDbContext())
using (MyDbContext context = new())
Второй вариант лучше. В первом варианте var не несёт никакого смысла и просто семантический мусор. Я бы на месте создателей Шарпа позволил бы в таких конструкциях вообще не писать ничего перед context.
public class MyRepository
{
private readonly MyDbContext _dbContext;
public MyRepository(MyDbContext dbContext)
{
_dbContext = dbContext;
}void DeleteUserById(int id)
{
using (var context = new MyDbContext())
context.Users.Remove(x => x.Id == id);
context.SaveChanges();
}
Когда я пишу свою репу, т.к. у меня нет БД и всё в файлах - это понятно, зачем мне своя репа. Когда вы тупо переписываете все функции EF, а потом ещё и юнит-тестируете их, вы просто душнилы. ))
А почему SaveChanges не вызывается автоматически при выходе за пределы контекста MyDbContext?
Ну например потому что ты из контекста мог только выбирать данные (select).
Душнила 2 года подряд ноет на автофоруме, что для него не сделали подхядящий электрический автобус.
Ну например потому что ты из контекста мог только выбирать данные (select).
Не в этом суть. То, что в контексте лишь выборка идёт, сам контекст прекрасно знает. Почему бы ему внутри себя не вызывать автоматом сохранение изменений при выходе за пределы контекста, если там кроме выборки ещё что-то изменилось? Ведь подавляющая часть сценариев - создали контекст, что-то сделали, сохранили изменения, вышли за предел. И все эти рутинные обязательные вызовы можно делать внутри себя.
Вот почему-то от ручного вызова Dispose каждый раз они нас избавили, от сохранения контекста - нет. Короче, там ещё улучшать и улучшать. Сишарп страдает от того, что слишком быстро идёт вперёд, но старьё не чистит. В результате в языке много мусора, в том числе синтаксического. По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость. Эта совместимость по большому счёту не нужна. Например, на моём проекте хоть и новый код и новые проекты в солюшене пишутся на новых версиях дотнета, но главный программист запрещает использовать подавляющее число нововведений из языка - чтобы консистентность со старым кодом (из времён .NET Framework 3.x, 4.x) сохранялась. Там же это, как его - догматы, что код должен по всему проекту быть по-возможности одинаковым. Я им, что с таким подходом этот проект будет вечно старьём, которое будет просто переводиться на новые рельсы (.NET 5, 6,...), но их возможности не исползовать. Там, где я на 3-5 строк пишу реализацию свойства по-новому, он расписывает на пол экрана в максимально старом стиле. Убивает читаемость кода в угоду глупой преемственности.
Кстати, новички, пришедшие на такой проект и обучавшиеся на новых версиях языка, скорее старый код меньше понимать будут, чем новый. Им будет просто непонятен смысл многословных простыней и кучи вложенных скобок там, где уже давно от этого можно было бы избавиться. Тут какой-то скрытый смысл умудрённых опытом мегасеньёров? - Нет, просто старпёры задеревенели и не хотят учить новое.
Душнила 2 года подряд ноет на автофоруме, что для него не сделали подхядящий электрический автобус.
Ещё недавно же каблучок был?
Автобус всяко лучше утыканной сверху и сзади всякими грузовыми обвесами "малолитражки".
И все эти рутинные обязательные вызовы можно делать внутри себя.
мне, имеющему опыт с SQL, логично в конце всех операций сделать Commit SaveChanges()
Тебе же никто не запрещает переписать Dispose твоего контекста
Там, где я на 3-5 строк пишу реализацию свойства по-новому, он расписывает на пол экрана в максимально старом стиле.
Можно пример?
Ещё недавно же каблучок был?
Так ты же сначала именно про них и пел
Автобус всяко лучше утыканной сверху и сзади всякими грузовыми обвесами "малолитражки".
у меня так-то двухлитровый дизель
Обвес это 5 раз в год - крепление для велосипедов сзади.
А стальные 360 дней красивый компактный комфортный быстрый автомобиль
Куда спешить со всей семьёй? Я еду 120+- и мне хватает. Тем более, что на большинстве мест, особенно на австрийских и итальянских автобанах, больше 130 не разрешено.
А у меня "обвес" это каждые выходные с мая по сентябрь, плюс отпуска. В малолитражку внутрь он не лезет, и сзади не цепляется.
Тебе же никто не запрещает переписать Dispose твоего контекста
Мне никто не мешает хоть весь .NET переписать. Но ценится больше то, что хорошо работает из коробки.
Можно пример?
Я приводил уже. Сейчас все проекты закрыты, поэтому по-памяти примерно так:
его вариант
private MyType myObject;
public MyType MyObject
{
get
{
if(myObject == null)
{
myObject = new MyType();
}
инициализация myObject
return myObject;
}
}
мой вариант
MyType myObject;
public MyType MyObject => myObject ??= new()
{
инициализация myObject
}
Или вот он говорит, чтобы я using обязательно использовал в старом стиле со скобочками (явное обозначение контекста), хотя без них всё проще и короче. И ещё несколько подобных моментов, которые вроде бы мелочь, но бесит, когда понимаешь, что можно проще, но нужно повторять шаг в шаг за дедками. А потому что в старых (15-летней давности) кусках кода так использовалось. Т.е. проект 15-летней давности нужно и через 10 лет от сегодняшнего дня писать как проект уже 25-летней давности. А то неконсистентно. То, что новый прогер, пришедший на проект, такую древность может уже и не понять - это консистентно.
я лучше не буду тянуться до _
Не вижу никаких, проблем - всё на автомате.
Но дискутировать по поводу code style смысла особого не имеет, у каждой команды свои соглашения и хотя не все с ними согласны, нужно делать как договорились.
Из этого можно сделать вывод, что для всех классов подобного типа не следует писать юнит тесты их просто следует называть интеграционными тестами.
1. Мы не про класс а про метод. Про конкретный метод. Из этого одного примера не надо делать далекоидущие выводы для каких-то "классов подобного типа".
2. Кого "их" называть? Тесты, которым для работы нужна БД? Да, их просто следует называть интеграционными.
Этот подход можно пользовать если мы хотим тестировать исключительно Query, а вот с Command будет посложнее, пусть даже база будет в локальном докере.
...Это самое малое что меня будет интересовать в данном случае. А вот загрузится ли полностью владелец или пользователи будет гораздо интереснее.
А если там еще и джойны есть, то есть что проверять.
Статическая база никак не подходит.
Это всё абсолютно не важно. Прилепил базу - прекращай называть тест "юнит-тестом". Ничего больше. Что сложного-то? А в своем интеграционном тесте можешь тестировать хоть джойны в докере, хоть простенькие селекты в in-memory.
using (var context = new MyDbContext())
using (MyDbContext context = new())
>Второй вариант лучше
Можно спорить до потери сознания и каждый останется при своем мнении.
Когда-то удобен var, когда то нет. В данном случае, мне больше нравится 1й.
По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость.
Вот класс, открываешь старый проект, а он вчера компилился, а сегодня уже нет.
Нет, просто старпёры задеревенели и не хотят учить ново
А вот не старпёр уже вовсю пользует primary constructor или всё же нет?
В чем преимущества вашего метода?
Метод не мой, всего лишь рекомендация руководящей партии - DbContext in dependency injection for ASP.NET Core
https://learn.microsoft.com/en-us/ef/core/dbcontext-config...
"It is generally better to inject the database context (MyDbContext) through the constructor rather than instantiating it directly within each method call. This approach follows the principle of dependency injection and allows for better testability and flexibility."
А приведенный вариант не очень гибкий как в вопросах тестирования, так и для модификации.
А если время жизни контекста и репозитория совпадают со временем жизни запроса, то отличий в функциональности пока не вижу.
Когда-то удобен var, когда то нет. В данном случае, мне больше нравится 1й.
Тут не удобство, а элементарная логика. Если с правой стороны объявлен тип, то с левой писать его ещё раз не имеет смысла. Ну кроме случаев полиморфизма. Но дать возможность не писать лишнее слово там, где это не нужно - нужно.
По-моему, было бы неплохо в какой-нибудь версии отменить обратную совместимость.Вот класс, открываешь старый проект, а он вчера компилился, а сегодня уже нет.
Для этого есть необратимые конвертеры старого в новое. Куча программ так и работает - либо конвертим в новое, либо сидим на старой версии. Тот же Unity, многие пакеты 3D (и не только) моделирования. Да и сами языки некоторые идут по таким стопам. Вроде, Питон в каких-то версиях не совместим. Потом из мира веба - Ангуляр. У Яблока это вообще возведено в принцип работы - как с пользователями, так и с разработчиками (Swift).
Это лучше, чем копить мусор в языке. Если копить, рано или поздно придётся его похоронить. Или таки выпустить версию без совместимости и "начать с чистого листа".
А вот не старпёр уже вовсю пользует primary constructor или всё же нет?
Я пока нет. Но если встретится подходящее место, где он будет удобен - буду.
Прилепил базу - прекращай называть тест "юнит-тестом"
Как будет подобное соглашение в команде, можно и переназвать. Но пока не вижу особого смысла в смене названия.
Про конкретный метод
Все методы в классе практически одинаковые _dbContext.xxxx;
Что сложного-то?
То что уже есть группа интеграционных тестов и эта группа придерживается другой классификации.
Если с правой стороны объявлен тип, то с левой писать его ещё раз не имеет смысла. Ну кроме случаев...
ну вот именно, что кроме случаев...
И в какой-то стороне обязательно нужно.
Но дать возможность не писать лишнее слово там, где это не нужно - нужно.
если имеемся в виду убрать var? Не думаю что это просто с точки зрения компилятора, да и большой бардак получается при этом.
Для этого есть необратимые конвертеры старого в новое.
Эти все рассуждения хороши пока нет тонн старого кода.
Кто даст 100% гарантию того, что после конвертации всё будет работать как и раньше?
Как минимум, нужно проводить дополнительное тестирование. А на это времени просто нет.
Я пока нет.
ну вот именно, как будут подходящие условия...
Дело то не в том знаешь или нет, а в том есть ли условия для этого.
Вот если такого мужика весной или осенью увидишь, что можно сказать?

Как будет подобное соглашение в команде, можно и переназвать. Но пока не вижу особого смысла в смене названия.
Дааа... "И эти люди запрещают мне ковырятся в носу" (с)
Может намекнуть команде, что назвать вещи надо так, как они называются? Ну, чисто по приколу. Чтобы вас понимать было можно.
P.S. А потом ходят такие "командные" и рассказывают о юнит-тестах, которые они не пишут, потому что они очень долго выполняются. А ты сидишь и гадаешь что же он имел в виду?
Может намекнуть команде, что назвать вещи надо так, как они называются?
Пока, что все согласны с тем как всё называется ![]()
https://www.bitiniyan.com/2019/02/02/how-to-write-unit-tes...
И ковыряйтесь в носу, сколько душе угодно. И мы будем в своем тоже ковыряться. Главное, чтобы не увидели как мы это делаем вместе
Значит если базу мОкаем - эту юнит тест, а если нет, то уже интеграционный - так?
Чтобы вас понимать было можно.
Проблем с пониманием пока не было, а вот если переименуем то точно появятся.
если имеемся в виду убрать var? Не думаю что это просто с точки зрения компилятора, да и большой бардак получается при этом.
Проблемы разработки компилятора меня не волнуют - я пользователь.
Какой бардак? Вам трёх попыток хватит, чтобы угадать, какой тип у myVariable?
myVariable = new MyType();
или
MyType myVariable = new();
Заметьте, что сейчас второй вариант полностью валидный. Но это зеркально первому. А первый - не валидный.
Кто даст 100% гарантию того, что после конвертации всё будет работать как и раньше?
Как минимум, нужно проводить дополнительное тестирование. А на это времени просто нет.
Если у вас не проект-однодневка, то вам в любом случае когда-то придётся всё конвертировать, переходить, тестировать. И лучше делать это, когда нового накопилось не так много, чем через 10-15 лет.
Вот если такого мужика весной или осенью увидишь, что можно сказать?
"Мистер Сандерс, не узнаю вас в гриме!"
))
Пока, что все согласны с тем как всё называется
Да пожалста. Хоть горшком называйте. Только не удивляйся что за пределами команды тебя понимать не будут.
Значит если базу мОкаем - эту юнит тест, а если нет, то уже интеграционный - так?
Где-то так, да.
На всякий случай (а то тут такие вопросы всплвали, а где конкретно про БД написано...): это не значит что если мы заменили доступ к базе моком, а к (например) LDAP оставили как есть, то такой тест можно называть юнит-тестом. (а чо, "если базу мОкаем - юнит тест", а про LDAP не написано нигде!)
Проблемы разработки компилятора меня не волнуют - я пользователь.
Хочу бусик, чтобы за секунды доставлял меня до моря.
Проблемы разработчиков авто меня не волнуют - я пользователь.
чтобы угадать, какой тип у myVariable
Мне не нужно гадать, я хочу увидеть и знать
Если у вас не проект-однодневка, то вам в любом случае когда-то придётся всё конвертировать, переходить, тестировать.
Как раз наоборот. Если проекту много лет, то его ни в коем случае нельзя трогать. Любые изменения только в крайнем случае.
Если есть бюджет, то лучше начать с нуля.
Только не удивляйся что за пределами команды тебя понимать не будут.
Скорее наоборот. Мне нужно некое определение и так как Вы его интерпретируете я пока не нахожу
Скорее - A more important distinction is whether the unit you're testing should be sociable or solitary
Хочу бусик, чтобы за секунды доставлял меня до моря.
Проблемы разработчиков авто меня не волнуют - я пользователь.
Нормальная инфраструктура зарядок, и запас хода не как у скутера-переростка. То, что сейчас - издевательство над покупателем.
чтобы угадать, какой тип у myVariableМне не нужно гадать, я хочу увидеть и знать
В том-то и дело, что по обеим моим записям увидел и всё понял.
у каждой команды свои соглашения и хотя не все с ними согласны, нужно делать как договорились.
Ну вот я и делаю, хотя и не согласен.
Фаулер остался в 90-х. Ну, в начале 2000-х. Почему-то. Когда то, что он называет "sociable" было единственным способом. Изолировать тестируемый "юнит" было можно. Но на это уходило немало времени. А с фреймворками для моков ему было уже лень разбираться. Да и не работал он уже. За прошедшие с тех пор почти 30 лет, люди поняли что чем изолированней, тем для юнит тестов лучше (а вообще и для всех, кроме end-to-end или nfr-тестов вроде нагрузочных). Увидели что легко изолируемый код ещё и легче расширять, чем неизолируемый. Придумали FIRST. А определение... В индустрии программирования с этим вообще-то большие проблемы. Ни IETF RFC, ни ISO нормы для юнит-тестов нет. ISTQB ими не заморачивается, это дело программистов. Так что только мнения и опыт.
Нормальная инфраструктура зарядок
Вообще-то было совсем про другое, а пример чтобы было просто более понятно.
То, что сейчас - издевательство над покупателем.
А это как тогда назвать?

что по обеим моим записям увидел и всё понял.
А хотя бы так? Тоже всё понятно?
myVariable = new MyType();
...
myVariable = new MyType2();
...
myVariable = new MyType2() + new MyType2();
Фаулер остался в 90-х.
А кто тогда не остался?
Так что только мнения и опыт.
Согласен, вот и хочу насобирать мнения для начала.
Или вот он говорит, чтобы я using обязательно использовал в старом стиле со скобочками (явное обозначение контекста), хотя без них всё проще и короче.
Как раз в случае с контекстом я хочу видеть момент его контекста
Но это таким модным молодежным не понять.
Ну сэкономил 5 сток, какой молодец. А что при чтении твоего когда взрывается моск, пофиг)
И вообще, почему не так?
private MyType myObject = new MyType()
{
инициализация myObject
};public MyType MyObject => myObject;
Если с правой стороны объявлен тип, то с левой писать его ещё раз не имеет смысла
поэтому его никто и не пишет, а ограничиваются словом var, Карл.
Если с правой стороны объявлен тип, то с левой писать его ещё раз не имеет смыслапоэтому его никто и не пишет, а ограничиваются словом var, Карл.
А без слова можно?
private MyType myObject = new MyType() { инициализация myObject };public MyType MyObject => myObject;
Можно и так. По мне, так даже для онли геттеров нужно сделать поддерживающее поле по-умолчанию. Отдельное явное объявление поля - просто лишний код. Если нужно его как-то особенно реализовать - делаешь сам. А если стандарт - пусть будет автоматическое по-умолчанию. Т.е. что-то типа такого или такого
public MyType MyObject => ??= new()
{
инициализация myObject
}public MyType MyObject ??= new()
{
инициализация myObject
}