Ответ
Ключевое различие между dynamic, var и object заключается в времени проверки типов и необходимости приведения.
-
var— вывод типа на этапе компиляции (compile-time). Это не тип, а указание компилятору самому определить и подставить статический тип на основе выражения инициализации. После определения тип фиксируется.var number = 10; // Компилятор определяет тип как `int` // number = "text"; // ОШИБКА КОМПИЛЯЦИИ: нельзя присвоить string переменной типа int -
dynamic— обход проверки типов на этапе компиляции. Тип и операции проверяются только во время выполнения (runtime). Это может привести к исключениямRuntimeBinderException, если операция недопустима.dynamic value = 10; value = "text"; // OK, тип меняется int length = value.Length; // OK на этапе компиляции, но упадет в runtime, т.к. у int нет свойства Length -
object— корневой тип системы. Все типы наследуются отobject. Для работы с конкретным типом требуется явное приведение (упаковка/распаковка для значимых типов).object obj = 10; // Упаковка (boxing): int -> object int num = (int)obj; // Распаковка (unboxing): object -> int (требуется явное приведение) // string str = (string)obj; // InvalidCastException в runtime
| Сводная таблица: | Ключевое слово | Проверка типа | Безопасность | Приведение | Основное назначение |
|---|---|---|---|---|---|
var |
Компиляция (статическая) | Высокая | Не требуется | Упрощение синтаксиса, LINQ-запросы | |
dynamic |
Выполнение (динамическая) | Низкая | Не требуется | Работа с COM, динамическими языками (Python), отражение | |
object |
Компиляция (к object) |
Средняя | Требуется явное | Общие контейнеры, полиморфные коллекции |
Практическое правило: Используйте var для локальных переменных, когда тип очевиден из правой части. Используйте dynamic только при необходимости взаимодействия с динамическими системами, осознавая риски. Используйте object, когда нужна общая ссылка на данные неизвестного заранее типа.
Ответ 18+ 🔞
А, ну это классика, блядь! Три штуки, которые новичков в C# вводят в ступор, как будто им в жопу кирпич засунули. Сейчас разжую, как бабушка котлету.
Смотри, вся разница — когда компилятор тебе мозги выносит за неправильные типы. Вот и вся магия.
-
var— это просто лень писать длинные типы, а компилятор — не дурак. Ты ему говоришь: «Сам догадайся, что тут». Он смотрит на правую часть, определяет тип раз и навсегда при компиляции и подставляет его, будто ты его сам написал. Всё. Тип статический, менять его потом — хуй тебе, а не смена типа.var digit = 42; // Компилятор видит 42 и думает: «А, ну это int, епта». // digit = "сорок два"; // А тут он тебе сразу в редакторе подсветит красным: «Иди нахуй, тут int, а ты string суёшь!» — ошибка компиляции. -
dynamic— это полная анархия и «поверю на слово». Ты компилятору говоришь: «Отстань от меня, я сам разберусь в момент выполнения». Он такой: «Окей, похуй». И проверяет хуйню твою только когда программа уже бежит. Это как ходить по минному полю в темноте — шагнул не туда, и тебе в ебальникRuntimeBinderExceptionприлетает.dynamic stuff = 100500; stuff = "сто тысяч"; // Да похуй, меняй. Компилятор молчит. int len = stuff.Length; // На компиляции — тишина. А в рантайме — БАБАХ! — исключение, потому что у числа 100500 свойства Length нет, дурачок. -
object— это дед всех типов, универсальный холодильник. В него можно засунуть что угодно: пирожок (int), селёдку (string), бутылку пива (любой класс). Но чтобы это потом достать и съесть, надо точно помнить, что ты туда положил, и явно привести обратно. Иначе — либо ошибка компиляции, либо тебя в рантаймеInvalidCastExceptionтрахнет.object box = 777; // Упаковал int в object (boxing). int num = (int)box; // Распаковал обратно (unboxing) — ок. // string text = (string)box; // Компилятор пропустит, но при запуске — словишь каст эксепшн, потому что в коробке не строка, а число.
Короче, таблица, чтобы вообще не ебеть мозг:
| Штука | Когда проверяет типы | Надёжность | Нужно ли приводить? | Зачем вообще нужно? |
|---|---|---|---|---|
var |
При компиляции | Высокая, статическая | Не нужно | Не париться писать длинные типы в LINQ или когда Dictionary<string, List<MySuperPuperClass>> лень выводить. |
dynamic |
При выполнении (runtime) | Низкая, можно выстрелить в ногу | Не нужно | Когда работаешь с какой-то ебейшей динамической хуйнёй: COM-объектами, питоном, рефлексией. |
object |
При компиляции (к object) | Средняя, можно налажать с кастом | Требуется явное | Когда нужен общий ящик для всего подряд, например, в старой необобщённой коллекции ArrayList. |
Простое правило жизни:
Используй var везде, где справа и так понятно, что за тип. Это просто удобно.
dynamic — только если реально приперло и без динамики никуда, и ты готов ловить исключения.
object — когда пишешь какую-то архаичную хуйню или нужен максимально общий контейнер, и ты не боишься кастов.
Вот и вся философия, блядь. Не усложняй.