C# и .NET Framework: что это, CLR и популярные фреймворки C#

C# и .NET Framework: что это, CLR и популярные фреймворки C# Полезное

C# — язык программирования, а .NET — платформа, на которой выполняются программы на C#: среда выполнения CLR, стандартные библиотеки и инструменты сборки. .NET Framework — первая, только Windows-реализация этой платформы; ее последняя версия 4.8.1 поддерживается, но новых возможностей не получает. Новые проекты пишут на кроссплатформенном .NET (бывший .NET Core), актуальная LTS-версия — .NET 10 с C# 14.

А фреймворки C# в бытовом смысле — прикладные надстройки поверх платформы: ASP.NET Core для веба, EF Core для баз данных, .NET MAUI, WPF и Avalonia для интерфейсов. Ниже — как устроено выполнение кода, чем .NET Framework отличается от .NET и что выбрать под задачу. Примеры проверены на .NET SDK 10.0.401 (runtime 10.0.12) в Linux-контейнере 24.09.2026.

Мини-словарь: что есть что

Эти слова постоянно путают, поэтому сначала разведем их.

Термин Что это Пример
C# Язык: синтаксис, типы, правила компиляции int Square(int x) => x * x;
.NET (платформа) CLR + библиотеки + SDK (компилятор, dotnet) .NET 10
.NET Framework Старая реализация .NET, только Windows 4.8.1
.NET Core, .NET 5+ Новая кроссплатформенная реализация .NET 8, .NET 10
CLR Среда выполнения: JIT-компиляция, сборка мусора, проверка типов часть любого .NET
CIL (IL) Промежуточный байт-код, в который компилируется C# ldarg.0, mul, ret
BCL Базовая библиотека классов List<T>, File, HttpClient
Прикладной фреймворк Каркас под класс задач, диктует структуру приложения ASP.NET Core, WPF

Важная граница: C# — не единственный язык .NET (есть F# и Visual Basic .NET), а .NET-программу можно запустить без Visual Studio — достаточно SDK и команды dotnet.

Как выполняется код на C

Путь программы от исходника до процессора выглядит так:

  1. Компилятор C# (Roslyn) превращает .cs-файлы в сборку .dll или .exe. Внутри — не машинный код, а CIL и метаданные о типах.
  2. При запуске CLR загружает сборку и проверяет метаданные.
  3. JIT-компилятор переводит метод в машинный код при первом вызове. Повторные вызовы используют уже готовый код.
  4. Сборщик мусора (GC) сам освобождает память объектов, на которые больше нет ссылок.

Это упрощенная модель. В современном .NET есть многоуровневая компиляция (сначала быстрый JIT, потом оптимизированный для «горячих» методов), предкомпиляция ReadyToRun и Native AOT, при котором приложение компилируется в машинный код заранее и JIT во время работы не нужен.

Управляемый и неуправляемый код

Управляемый код выполняется под контролем CLR: память освобождает GC, выход за границы массива дает исключение, а не порчу памяти. Весь обычный код на C# управляемый.

Неуправляемый код — нативные библиотеки на C/C++ и системные API. C# вызывает их через P/Invoke, но за память и корректность на той стороне CLR не отвечает. Режим unsafe в C# с указателями — промежуточный случай: код остается управляемым, но часть проверок снимается.

Пример: смотрим на CLR и CIL изнутри

Программа выводит, на какой среде она запущена, показывает байты CIL одного метода и выделяет память без ручного освобождения. Проект создается командой dotnet new console, запуск — dotnet run -c Release.

using System.Reflection;
using System.Runtime.InteropServices;

Console.WriteLine($"Среда выполнения: {RuntimeInformation.FrameworkDescription}");
Console.WriteLine($"ОС: {RuntimeInformation.OSDescription}");
Console.WriteLine($"Архитектура процесса: {RuntimeInformation.ProcessArchitecture}");

// Метод Square скомпилирован не в машинный код, а в CIL (промежуточный язык).
MethodInfo square = typeof(Calc).GetMethod(nameof(Calc.Square))!;
byte[] il = square.GetMethodBody()!.GetILAsByteArray()!;
Console.WriteLine($"CIL метода Square: {BitConverter.ToString(il)}");
Console.WriteLine($"Square(7) = {Calc.Square(7)}");

// Памятью управляет сборщик мусора (GC): освобождать объекты вручную не нужно.
long before = GC.GetTotalAllocatedBytes(precise: true);
var data = new byte[1_000_000];
long after = GC.GetTotalAllocatedBytes(precise: true);
Console.WriteLine($"Выделено под массив: ~{(after - before) / 1_000_000.0:F1} МБ, длина {data.Length}");

static class Calc
{
    public static int Square(int x) => x * x;
}

Вывод в контейнере mcr.microsoft.com/dotnet/sdk:10.0 (строки про ОС и архитектуру на вашей машине будут другими):

Среда выполнения: .NET 10.0.12
ОС: Ubuntu 24.04.5 LTS
Архитектура процесса: Arm64
CIL метода Square: 02-02-5A-2A
Square(7) = 49
Выделено под массив: ~1.0 МБ, длина 1000000

Разбор по шагам:

  • FrameworkDescription называет реализацию платформы. На .NET Framework там было бы .NET Framework 4.8..., на современном .NET — .NET 10.0.x.
  • Четыре байта 02-02-5A-2A — это CIL метода Square: ldarg.0 (положить аргумент на стек) дважды, mul (умножить), ret (вернуть). Машинный код для ARM64 или x64 из них строит JIT уже при запуске, поэтому одна и та же сборка работает на разных процессорах.
  • Массив на миллион байт создан без malloc и free: память выделил и позже освободит GC.

Одна оговорка: для такого однострочного метода отладочная и Release-сборка дали одинаковые байты. Если записать тот же метод с телом в фигурных скобках ({ return x * x; }), отладочная сборка (dotnet run без -c Release) выдает 00-02-02-5A-0A-2B-00-06-2A: добавляются nop, сохранение результата в локальную переменную и переход перед ret, которые упрощают пошаговую отладку. Release-сборка для этого варианта дает те же 02-02-5A-2A.

.NET Framework и .NET: в чем разница

Хронология коротко: .NET Framework 1.0 вышел в 2002 году, в 2016-м появился кроссплатформенный .NET Core 1.0. В 2020 году ветки объединили под именем .NET 5 (номер 4 пропустили, чтобы не путать с .NET Framework 4.x). С тех пор новая версия выходит каждый ноябрь: четные — LTS, нечетные — STS с более коротким сроком поддержки.

Критерий .NET Framework .NET (Core, 5+)
ОС Только Windows Windows, Linux, macOS
Актуальная версия 4.8.1, без новых возможностей .NET 10 LTS, новая версия каждый ноябрь
Установка Одна версия 4.x на систему, входит в Windows Несколько версий рядом, можно встроить в приложение
Исходный код Закрытый Открытый (MIT)
Веб ASP.NET MVC, Web Forms ASP.NET Core
Десктоп WinForms, WPF WinForms и WPF (только Windows), MAUI, Avalonia
Имя цели в .csproj net48, net481 net8.0, net10.0, net10.0-windows

Как выбирать:

  • Новый проект — .NET 10: LTS, кроссплатформенность, свежий C#.
  • Поддержка старого приложения на .NET Framework — оставаться на 4.8.1, пока нет бюджета на миграцию. Web Forms и серверная часть WCF в современный .NET не перенесены, для них миграция — это переписывание.
  • Библиотека для обоих миров — цель netstandard2.0 или несколько целей сразу (<TargetFrameworks>net48;net10.0</TargetFrameworks>).

Популярные фреймворки C# по задачам

Разница в терминах: платформа (.NET) исполняет код, библиотека (например, Newtonsoft.Json) вызывается из вашего кода, а фреймворк сам вызывает ваш код и задает структуру приложения.

Задача Фреймворк Где работает Когда брать иначе
Веб-API, сайты ASP.NET Core (Minimal API, MVC, Razor Pages) Windows, Linux, macOS, контейнеры Старый сайт на ASP.NET MVC 5 живет на .NET Framework
Интерактивный веб-интерфейс на C# Blazor (часть ASP.NET Core) Сервер или браузер через WebAssembly Для сложного SPA команда может выбрать JS-фреймворк
Работа с БД Entity Framework Core Везде, где .NET Нужен полный контроль SQL — микро-ORM или ADO.NET
Десктоп под Windows WPF, Windows Forms, WinUI 3 Только Windows Нужен Linux/macOS — Avalonia или MAUI
Кроссплатформенный UI .NET MAUI, Avalonia (сторонний) MAUI: Windows, macOS, Android, iOS; Avalonia: плюс Linux Только Windows — проще WPF
Игры Unity, Godot (C# как язык скриптов) Зависит от движка Unity исполняет C# на своем рантайме (Mono или IL2CPP), Godot 4 — на обычном .NET; экспорт C#-проекта Godot в веб пока не поддерживается
Тесты xUnit, NUnit, MSTest Везде, где .NET Выбор по стилю команды
Распределенные системы Orleans Везде, где .NET Обычный веб-сервис проще на ASP.NET Core

Мобильная разработка на Xamarin закрыта: его поддержка завершилась в 2024 году, преемник — .NET MAUI.

Частая ошибка: WinForms на неправильной цели

Кроссплатформенность .NET не делает кроссплатформенными WinForms и WPF. Вот проект, который пытается собрать WinForms-приложение с обычной целью net10.0:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
  </PropertyGroup>
</Project>

Фактический результат dotnet build (путь к SDK сокращен):

error NETSDK1136: The target platform must be set to Windows (usually by including '-windows' in the TargetFramework property) when using Windows Forms or WPF, or referencing projects or packages that do so.

Исправление — цель с суффиксом платформы: <TargetFramework>net10.0-windows</TargetFramework>. На Windows после этого проект собирается и запускается.

На Linux или macOS появится следующая ошибка:

error NETSDK1100: To build a project targeting Windows on this operating system, set the EnableWindowsTargeting property to true.

С <EnableWindowsTargeting>true</EnableWindowsTargeting> сборка проходит, но dotnet run в Linux-контейнере сообщает You must install or update .NET to run this application и Framework: 'Microsoft.WindowsDesktop.App'. Флаг разрешает только собрать проект вне Windows (например, на CI), запускать такое приложение по-прежнему нужно на Windows.

Как проверить, что установлено

Для современного .NET (Windows, Linux, macOS):

dotnet --list-sdks       # SDK: собирают проекты
dotnet --list-runtimes   # среды выполнения: запускают приложения

Вывод второй команды в том же контейнере:

Microsoft.AspNetCore.App 10.0.12 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 10.0.12 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Здесь видно, что в .NET «фреймворк» — еще и технический термин: Microsoft.NETCore.App — базовый общий фреймворк, Microsoft.AspNetCore.App — веб, а Microsoft.WindowsDesktop.App (WinForms/WPF) ставится только на Windows.

Версию .NET Framework 4.x на Windows показывает PowerShell — команда только читает реестр:

Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' | Select-Object Version, Release

Если не получилось

  • You must install or update .NET to run this application — на машине нет среды нужной версии. Сверьте версию из сообщения с выводом dotnet --list-runtimes и поставьте недостающий runtime.
  • Ошибка NETSDK1045 при сборке — SDK старше, чем цель в .csproj. Обновите SDK или понизьте TargetFramework.
  • Старая программа просит .NET Framework 3.5 — в Windows 10/11 он включается в «Компонентах Windows», а не ставится отдельным пакетом.
  • Удалять .NET Framework 4.x в Windows 10/11 не нужно и нельзя — это часть системы. При сбоях сначала обновления Windows, потом официальная утилита .NET Framework Repair Tool.

Выводы

  • C# — язык, .NET — платформа (CLR, библиотеки, SDK), .NET Framework — старая Windows-реализация этой платформы, остановленная на 4.8.1.
  • Код на C# компилируется в CIL, а в машинный код его переводит JIT при запуске (или заранее при Native AOT); памятью управляет GC.
  • Новые проекты — на .NET 10 LTS; .NET Framework остается для поддержки legacy-приложений.
  • «Фреймворки C#» подбирают под задачу: ASP.NET Core для веба, EF Core для БД, WPF/WinForms для Windows-десктопа, MAUI или Avalonia для кроссплатформенного UI.
  • WinForms и WPF работают только на Windows даже в современном .NET: цель net10.0-windows.

Где применяется / связь с практикой

Освойте тему на практике

Разница между языком, платформой и фреймворком всплывает с первого проекта: какую цель указать в .csproj, почему приложение не запускается на сервере, можно ли перенести старый сервис на Linux. Если хочется пройти путь от синтаксиса C# до приложений на .NET системно, с практикой и разбором кода, посмотрите курс «C#-разработчик. Базовый уровень». Отдельные темы по .NET и смежным технологиям разбирают на открытых уроках Otus.

FAQ

Можно ли писать на C# без .NET?
Практически нет: C#-компилятор выдает CIL, которому нужна среда выполнения. Это может быть .NET, Mono или рантайм игрового движка, а при Native AOT среда встраивается в сам исполняемый файл.

Нужно ли учить .NET Framework, если начинаю с нуля?
Начинать стоит с .NET 10. Знание .NET Framework понадобится при поддержке старых корпоративных приложений, и основы (C#, CLR, BCL) там те же.

.NET Standard — это еще одна платформа?
Нет, это спецификация общего набора API. Библиотека с целью netstandard2.0 подключается и к .NET Framework 4.6.1+, и к современному .NET.

OTUS Журнал
Скидка 5% 12-19 октября на курсы (popup)
Бесплатные открытые уроки (поп-ап)