C#MiddleExperience
Какие ошибки делают разработчики, переходящие на C# с другого языка или стека?
С Python: игнорирование типов, синхронный код в async-контексте. С Java: избыточные интерфейсы, путаница Optional vs Nullable. С JS/TS: дедлок через .Result вместо await. Системные: captive dependency в DI, не закрытые IDisposable-ресурсы. Лечится Roslyn-анализаторами и DI ValidateOnBuild.
Типичные ошибки при переходе на C# с другого языка
С Python
- Игнорирование типов. Python-разработчики привыкают к динамической типизации и используют
objectилиdynamicвместо конкретных типов, теряя преимущества компилятора. - Синхронный код вместо async. В Python asyncio — опциональный; в ASP.NET Core async — стандарт. Блокирующие вызовы (
Thread.Sleep, синхронные HTTP) приводят к thread pool starvation. - Неверная работа с None/null. Python-разработчики забывают про nullable reference types и
ArgumentNullException.ThrowIfNull, что приводит к NRE в production.
С Java
- Переиспользование Java-паттернов. В Java принято оборачивать каждый класс в интерфейс; в C# это избыточно для приватных реализаций. Избыток абстракций усложняет код без выгоды.
- Checked exceptions. В Java checked exceptions обязательны к обработке; в C# все исключения unchecked — без явных null-checks и guard clauses ошибки проявляются позже.
- Путаница Optional vs Nullable. Java Optional — обёртка-объект; C# nullable (
T?) — языковой механизм без дополнительных аллокаций.
С JavaScript/TypeScript
- Прототипная vs классовая модель. JS-разработчики иногда ищут прототипное наследование; в C# наследование строгое, без динамического добавления методов в runtime.
- Async/await похоже, но разное. В JS любой Promise можно await без объявления функции async; в C# нужен
asyncна метод, и смешивание с.Resultвызывает дедлок. - Строгая типизация дженериков. TypeScript допускает covariance почти везде; C# различает
in/outvariance на интерфейсах —IEnumerable<T>ковариантен,List<T>— нет.
Системные ошибки независимо от языка
- Captive dependency в DI. Singleton, захвативший Scoped DbContext — классика, которую компилятор не поймает.
- Blocking call в async context.
task.Resultилиtask.Wait()в методе с SynchronizationContext = дедлок. - Забытый using. Открытые
HttpClient,FileStream,DbConnectionбезusingисчерпывают системные ресурсы.
Как предотвращать
Code review с C#-specific checklists, Roslyn-анализаторы (Microsoft.CodeAnalysis.NetAnalyzers, SonarAnalyzer.CSharp), включённый <Nullable>enable</Nullable> и <TreatWarningsAsErrors>true</TreatWarningsAsErrors> в csproj, а также DI-валидация через ValidateOnBuild = true.
Подводные камни
- Не превращайте ответ в список запретов — объясняйте, почему ошибка возникает и как её обнаружить рано.
- Самые дорогие ошибки проявляются не на ревью, а под нагрузкой: thread pool starvation, LOH fragmentation, captive dependency.
- Анализаторы ловят много, но не всё: дедлоки и GC-паузы требуют нагрузочного тестирования.
What hurts your answer
- Перечислять ошибки без объяснения причин
- Не отличать beginner mistakes от production failure modes
- Не предлагать процесс, который предотвращает повторение ошибок
What they're listening for
- Знает типичные ошибки при работе с C#
- Понимает причины ошибок
- Предлагает практики prevention и early detection