C # частично интерпретируется или действительно скомпилирован?

По этому поводу существует много противоречивой информации. В то время как некоторые говорят, что C # скомпилирован (поскольку он компилируется в IL, а затем в собственный код при запуске), другие говорят, что он интерпретируется так, как требует .NET. EN Wiki говорит:

Многие интерпретируемые языки сначала компилируются в некоторую форму кода виртуальной машины, которая затем либо интерпретируется, либо компилируется во время выполнения в собственный код.

Так что я в полном замешательстве. Может ли кто-нибудь объяснить это ясно?


person John V    schedule 12.01.2012    source источник
comment
возможный дубликат Интерпретируется или компилируется C #?   -  person Cody Gray    schedule 12.01.2012
comment
Связанное сообщение - Если C # не интерпретируется, то зачем нужна виртуальная машина?   -  person RBT    schedule 12.07.2018
comment
inb4 кто-то изобретает язык, который распространяется как LLVM IR и требует, чтобы пользователи установили некий автономный экземпляр LLVM.   -  person SOFe    schedule 10.04.2019
comment
Я знаю, что это устарело, но я думаю, что он все еще актуален. Большинство обсуждений здесь происходит от разных определений интерпретируемого языка и компилируемого языка. Вопрос может быть улучшен путем (1) уточнения конкретного определения этих терминов OP или (2) отделения вопроса интерпретации и компиляции от вопроса о том, что доступно / стандартно для создания / запуска кода C #. Для тех, кто заинтересован в продвижении к компиляции C # .NET с опережением времени (Native AOT), см. это репо.   -  person teichert    schedule 14.01.2021


Ответы (13)


C # компилируется в IL компилятором C #.

Затем этот IL компилируется точно в срок (JIT) по мере необходимости на родном языке ассемблера хост-машины. Однако можно было бы написать среду выполнения .NET, которая вместо этого интерпретировала бы IL. Даже если бы это было сделано, я бы все равно утверждал, что C # - это компилируемый язык.

person Simon    schedule 12.01.2012
comment
Но почему тогда многие программисты считают его понятным языком? - person John V; 12.01.2012
comment
Лично я никогда не слышал, чтобы кто-нибудь называл C # интерпретируемым языком. - person jrummell; 12.01.2012
comment
Возможно, они просто ошибаются или неверно информированы. А может я ошибаюсь :-) - person Simon; 12.01.2012
comment
JIT-компиляция! = Интерпретируется - person spender; 12.01.2012
comment
Почему вы утверждаете, что C # - это компилируемый язык? Не могли бы вы подробнее рассказать об этом? - person Jo Smo; 13.09.2016
comment
@JoSmo csc.exe - это инструмент командной строки, который собирает C #. Расшифровывается как C-Sharp Compiler. - person Simon; 20.09.2016
comment
В C ++ опытный программист может делать такие вещи, как выбирать шаблоны вместо виртуальных методов, чтобы повлиять на эффективность создаваемого кода. В C # на самом деле это не так. Между программистом и не совсем скомпилированным кодом слишком много слоев. Более того, нет необходимости поставлять среду выполнения виртуальной машины с кодом C ++. С C # вам по-прежнему нужен какой-то интерпретатор. Это не совсем скомпилировано. - person Erik Aronesty; 18.09.2018
comment
@ErikAronesty Вам не нужен интерпретатор, но вам нужен jit-компилятор. - person Simon; 19.09.2018
comment
Если процессы, такие как сборка мусора, остаются под контролем механизма JIT во время выполнения программы ... это интерпретатор. Если вам нужно отправить программу для запуска вашей программы ... она интерпретируется. Глупо переименовывать вещи на основе эффективности интерпретации. - person Erik Aronesty; 21.09.2018
comment
@ErikAronesty Это еще не то, что могло бы сделать C # интерпретируемым языком. Когда вы запускаете код C #, байтовый код компилируется в собственный код и кэшируется средой CLR. - person John V; 29.10.2018

Чисто скомпилированный язык имеет некоторые преимущества. Скорость, как правило, и часто рабочий размер набора. У чисто интерпретируемого языка есть некоторые преимущества. Гибкость, заключающаяся в отсутствии необходимости в явном этапе компиляции, что позволяет нам редактировать на месте, и часто более простая переносимость.

В этом случае язвительный язык уместен в середине.

Это уже одна причина, по которой мы можем думать о языке с джиттингом как о скомпилированном или интерпретируемом, в зависимости от того, какая позиция по какой метрике нам важна, а также от наших предубеждений за и против одного или другого.

C # также может быть скомпилирован при первом запуске, как это происходит в ASP.NET, что делает его близким к интерпретируемому в этом случае (хотя он по-прежнему компилируется в IL, а затем в этом случае джиттируется). Конечно, в этом случае он обладает почти всеми преимуществами интерпретации (по сравнению с VBScript или JScript, используемыми в классическом ASP), а также многими преимуществами компиляции.

Строго говоря, никакой язык не может быть изменен, интерпретирован или компилирован как язык. Мы можем использовать NGen C # в машинном коде (хотя, если он выполняет что-то вроде динамической загрузки сборки, он все равно будет использовать IL и джиттинг). Мы могли бы написать переводчика для C или C ++ (это сделали несколько человек). Однако в наиболее распространенном варианте использования C # компилируется в IL, который затем прерывается, что не совсем классическое определение интерпретируемого или скомпилированного.

person Jon Hanna    schedule 12.01.2012
comment
Я согласен с no language is jitted, interpretted or compiled qua language. Я немного узнал о python, который сначала компилируется в byteCode, а затем во время выполнения byteCode интерпретируется интерпретатором соответствующей ОС. Этот факт только усилил мое изумление, вызванное определениями скомпилированных, изменяемых и интерпретируемых языков. - person RBT; 04.07.2016
comment
Языки JIT могут быть быстрее, чем родные. Вы знаете, что у gcc есть инструментарий, где он выводит файл измерения производительности при запуске, а затем передает его обратно в gcc для компиляции более оптимизированного двоичного файла? И JVM, и CLR делают это постоянно. - person John Moser; 24.07.2017

Слишком много семантики и утверждений, основанных на мнении.

Во-первых: C # не интерпретируемый язык; CLR и JVM считаются «средами выполнения» или «промежуточным программным обеспечением», но то же имя применяется к таким вещам, как Perl. Это создает путаницу среди людей, озабоченных именами.

Термин «интерпретатор», относящийся к среде выполнения, обычно означает, что существующий код интерпретирует некоторый неродной код. Есть две большие парадигмы: синтаксический анализ читает необработанный исходный код и выполняет логические действия; Выполнение байт-кода сначала компилирует код в неродное двоичное представление, для интерпретации которого требуется гораздо меньше циклов ЦП.

Изначально Java была скомпилирована в байт-код, а затем прошла через интерпретатор; теперь JVM считывает байт-код и своевременно компилирует его в собственный код. CIL делает то же самое: CLR использует своевременную компиляцию собственного кода.

Рассмотрите все комбинации выполнения исходного кода, выполнения байт-кода, компиляции в собственный, своевременной компиляции, выполнения исходного кода через компилятор в своевременный исходный код и т. Д. Семантика компилирования или интерпретации языка становится бессмысленной.

В качестве примера: многие интерпретируемые языки используют своевременную компиляцию байт-кода. C # компилируется в CIL, который JIT компилируется в родной; Напротив, Perl немедленно компилирует сценарий в байт-код, а затем запускает этот байт-код через интерпретатор. Вы можете запускать сборку C # только в формате байт-кода CIL; вы можете запускать Perl-скрипт только в формате необработанного исходного кода.

Оперативные компиляторы также используют множество внешних и внутренних инструментов. Среда выполнения отслеживает выполнение различных функций, а затем корректирует макет кода для оптимизации ветвей и организации кода для конкретного потока выполнения. Это означает, что код JIT может работать быстрее, чем код, скомпилированный в машинном коде (как обычно C ++ или как C # работает через IL2CPP), потому что JIT подстраивает свою стратегию оптимизации к фактическому случаю выполнения кода во время его выполнения.

Добро пожаловать в мир компьютерного программирования. Мы решили сделать его предельно сложным, а затем присвоить всему непонятные имена. Цель состоит в том, чтобы вызвать ожесточенную войну из-за определения слов, не имеющих практического значения.

person John Moser    schedule 17.01.2016
comment
JVM интерпретирует байт-код, а затем компилирует некоторые тела методов / циклов в собственный код. Эта компиляция может происходить параллельно с интерпретацией байт-кода, и код может быть заменен на «горячую» замену. - person Steves; 24.04.2017
comment
Я не могу найти ссылку на это. Насколько я понимаю, JVM интерпретирует байт-код при его выполнении с помощью JIT, то есть: когда он встречает байт-код, с которым еще не работал во время текущего запуска, он запускает его через JIT и выполняет полученный блок собственного кода. JIT-and-execute дешевле, чем интерпретация байт-кода, и реализация обеих систем очень сложна. - person John Moser; 24.07.2017
comment
Касса например slideshare.net/ZeroTurnaround/. Вы описываете то, что делает .NET. Я описал то, что, например, Hotspot JVM работает, и да, она довольно сложна, поэтому она разрабатывалась некоторое время. Вам нужно интерпретировать код байт-кодом, чтобы получить информацию о профиле (подумайте: какой, если ветвь выполнялась большую часть времени и т. Д.), Которая используется в оптимизирующем компиляторе (это, если ветка никогда не была взята, не тратьте слишком много ресурсы по его оптимизации). - person Steves; 29.07.2017
comment
На самом деле perl теперь тоже джиттируется. - person Erik Aronesty; 18.09.2018
comment
Вы можете использовать профилирование в машинном коде. В gcc есть инструменты профилирования как таковые. Компилятор может идентифицировать итератор цикла и добавлять код для сравнения его состояний входа и выхода; он может устанавливать переменную при переходе на ветку; и так далее. Это может происходить для подсчета количества вызовов, количества циклов, количества переходов и т. Д. Между каждым анализом данных профилирования JIT. Это стоит несколько циклов - меньше, чем интерпретация байт-кода. - person John Moser; 04.04.2019
comment
JVM не всегда JIT-компилирует байт-код в собственный код. Наиболее часто используемая JVM под названием HotSpot - stackoverflow.com/questions / 16568253 / - имеет стратегии, которые решают, требовать ли накладных расходов на компиляцию или интерпретировать. Стратегия довольно проста по идее, она интерпретируется изначально, но JIT-компилируется, если метод запускается несколько раз. Он может подсчитывать вызовы методов, потому что JVM уже берет на себя накладные расходы, отслеживающие их (для информации stracktrace и т. Д.). TL; DR: в Java код инициализации для однократного выполнения, вероятно, интерпретируется. - person radfast; 29.05.2020

Если вы чувствуете, знаете или придерживаетесь старой закалки, что скомпилированный EXE переходит от исходного кода к машинному коду, то интерпретируется C #. Если вы думаете, что скомпилированный означает преобразование исходного кода в другой код, такой как байтовый код, тогда да, он преобразован. Для меня интерпретируется все, что требует обработки во время выполнения для работы в ОС, для которой она была создана.

person ChicagoBob    schedule 27.06.2014
comment
Мы не спрашиваем мнения, и для меня это мнение. Это не форум. - person Angelo Mascaro; 07.11.2017
comment
К сожалению, суть вопроса - мнение. - person Erik Aronesty; 18.09.2018

Посмотрите здесь: http://msdn.microsoft.com/library/z1zx9t92

Исходный код, написанный на C #, компилируется на промежуточный язык (IL), который соответствует спецификации CLI.

(...)

При выполнении программы C # сборка загружается в среду CLR, которая может выполнять различные действия в зависимости от информации в манифесте. Затем, если требования безопасности соблюдены, CLR выполняет своевременную (JIT) компиляцию для преобразования кода IL в собственные машинные инструкции.

person psur    schedule 12.01.2012
comment
Спасибо, поэтому, если я правильно понимаю, путаница с intepretes может исходить от виртуальной машины (CRM), которая необходима, однако это не настоящий интерпретатор. - person John V; 12.01.2012

Прежде всего давайте разберемся с определениями интерпретируемого и скомпилированного.

«Компилировать» (когда речь идет о коде) означает переводить код с одного языка на другой. Обычно из исходного кода, читаемого человеком, в машинный код, который целевой обработчик может ... обработать.

«Интерпретировать» (при ссылке на код) ТАКЖЕ означает перевод кода с одного языка. к другому. Но на этот раз он обычно используется для перехода от исходного кода, читаемого человеком, к промежуточному коду, который принимает виртуальная машина, которая интерпретирует его в машинный код.

Для ясности
Исходный код -> Компилятор -> Машинный код
Исходный код -> Компилятор -> Байт-код -> Интерпретатор -> Машинный код

Теоретически любой язык можно интерпретировать или скомпилировано. Обычно Java компилируется в байт-код, который интерпретируется виртуальной машиной Java в машинный код. C # обычно интерпретируется в байт-код, который компилируется CLR, средой CLR, другой виртуальной машиной.

Безусловно, все это - маркетинговый трюк. Термин «интерпретируемый» был добавлен (или, по крайней мере, его употребление увеличилось), чтобы продемонстрировать, насколько аккуратно своевременная компиляция была. Но они могли просто использовать «скомпилированный». Различие скорее связано с изучением английского языка и бизнес-тенденций, чем с чем-либо техническим.

person Philip    schedule 20.11.2012
comment
В интерпретаторе машинный код не создается во время выполнения, выполняется только существующий машинный код. По этому стандарту совершенно неправильно называть Common Language Runtime интерпретатором. - person Ben Voigt; 28.06.2014

C # и интерпретируется, и компилируется за время своего существования. C # скомпилирован на виртуальный язык, который интерпретируется виртуальной машиной.

Путаница проистекает из нечеткой концепции «компилируемого языка».

«Скомпилированный язык» в некотором смысле неправильное употребление, потому что скомпилированный или интерпретируемый - это свойство не языка, а среды выполнения.

например Вы можете написать интерпретатор C, но люди обычно называют его «компилируемым языком», потому что реализации C компилируются в машинный код, а язык был разработан с учетом компиляции.

person ajfabbri    schedule 20.01.2013
comment
Нет, настольная виртуальная машина .NET (называемая Common Language Runtime) имеет JIT-компилятор, а не интерпретатор. Напротив, .NET Microframework, обнаруженный на крошечных встроенных устройствах, которые могут даже не поддерживать модификацию кода времени выполнения, фактически интерпретирует IL. - person Ben Voigt; 28.06.2014
comment
Источник - ›(компилятор) -› Промежуточный язык - ›(интерпретатор) -› Собственный код. Я рассматриваю JIT как оптимизацию интерпретатора. Это в основном кеширование на уровне интерпретатора. Вы можете вызвать компиляторы обоих шагов, если хотите. - person ajfabbri; 11.07.2014

Для большинства языков, если не для всех, требуется интерпретатор, который переводит их сценарии в машинные коды, чтобы процессор мог понять и выполнить его!

Каждый язык обрабатывает процесс перевода по-своему!

Например, «AutoIt» - это то, что мы можем описать как 100% интерпретируемый язык!

Почему?

Потому что интерпретатор "AutoIt" ​​нужен постоянно, пока выполняется его сценарий! См. Пример ниже:

Loop, 1000
Any-Code

Интерпретатор AutoIt должен был бы 1000 раз преобразовать Any-Code в машинный код, что автоматически делает AutoIt медленным языком!

С другой стороны, C # по-разному обрабатывает процесс перевода, интерпретатор C # требуется только один раз, перед выполнением сценария, после этого он больше не требуется во время выполнения сценария!

Интерпретатору C # пришлось бы только один раз преобразовать Any-Code в машинный код, что автоматически делает C # быстрым языком!

Итак, в основном,

  • Язык, для которого требуется интерпретатор во время выполнения скрипта, называется «интерпретируемым языком»!

  • Язык, для которого интерпретатор требуется только один раз (перед выполнением скрипта), называется "компилируемым языком"!

Наконец-то,

  • «AutoIt» - это «язык интерпретации»!

  • «C #» - это «компилируемый язык»!

person User    schedule 24.01.2019

Я считаю, что это довольно старая тема.

С моей точки зрения, интерпретируемый код будет проходить через интерпретатор, построчно переводить и выполнять одновременно. Как и пример javascript, это интерпретируемый код, когда строка javascript сталкивается с ошибкой, сценарий просто прерывается.

Во время компиляции код проходит через компилятор, переводит весь код в другую форму кода сразу, не выполняя его предварительно. Казнь в другом контексте.

person Jonny    schedule 13.10.2017
comment
JavaScript либо JIT-компилируется немедленно, как C #, либо выполняется так же, как HotSpot JVM, интерпретируется до тех пор, пока части кода не станут горячими, после чего он будет JIT-компилирован с помощью оптимизирующего компилятора. Это зависит от движка JavaScript. JavaScript не интерпретировался более 10 лет. - person Julian Jensen; 20.07.2019

C #, как и Java, имеет гибридный языковой процессор. Гибридные процессоры выполняют как интерпретацию, так и компиляцию.

person P.Brian.Mackey    schedule 14.03.2015

Поскольку компьютер может выполнять только двоичный код, любой язык приведет к созданию двоичного кода в тот или иной момент. Возникает вопрос: позволяет ли язык создавать программу в двоичном коде? Если да, то это компилируемый язык: по определению «скомпилированный» в «скомпилированном языке» относится к компиляции в двоичный код, а не к преобразованию в некоторый промежуточный код. Если язык приводит к созданию такого промежуточного кода для программы, ему потребуется дополнительное программное обеспечение для выполнения двоичной компиляции из этого кода: тогда это интерпретируемый язык. Является ли программа, "скомпилированная" C #, исполняется непосредственно на машине без какого-либо другого программного обеспечения, установленного на этой машине? если нет, то это интерпретируемый язык. Для интерпретируемого языка это интерпретатор, который будет генерировать базовый двоичный код, большую часть времени динамически, поскольку этот механизм является основой гибкости таких языков. rem. : иногда это не выглядит очевидным, потому что интерпретатор встроен в ОС

person ClearMind    schedule 29.08.2017
comment
По этому определению QBasic был компилятором. Это явно горшок. C # также является интерпретируемым языком, с некоторым JIT для оптимизации. Конечно, вы также можете NGen .Net IL, но вы теряете оптимизацию, которую может выполнить JITter. То, что вы получаете в IL, - это список данных, используемых для диспетчеризации вызовов подпрограмм, машинный код не генерируется и не выполняется, за исключением случаев, когда среда выполнения видит интенсивное использование и заменяет запуски данных p-кода машинным кодом JITted, чтобы заменить диспетчеризацию вызовов. - person Bob77; 08.11.2017

Если мы согласны с определением интерпретатора, «В информатике интерпретатор - это компьютерная программа, которая непосредственно выполняет, т. Е. Выполняет инструкции, написанные на языке программирования или сценариях, без необходимости их предварительной компиляции в машинный язык. программа. »Нет сомнений: C # не интерпретируемый язык.

Переводчик в Википедии

person Angelo Mascaro    schedule 07.11.2017

C # - компилируемый язык.

Вероятно, поскольку я тоже встречал подобные мнения, тот факт, что кто-то думает, что существует интерпретатор для языка C #, связан с такими проектами, как

Консоль интерпретатора C #

или, например, знаменитый

LinqPAD

где вы можете написать просто строки кода и выполнить их, что заставляет думать, что это Python как язык, то есть < сильный> неправда. Он компилирует эти строки и выполняет их, как обычный компилируемый язык программирования (с точки зрения рабочего процесса).

person Tigran    schedule 12.01.2012
comment
Спасибо. Но все же C ++ и C # с этой точки зрения будут скомпилированными языками. Но я думаю, что это не так ясно, поскольку в C ++ он напрямую компилируется в собственный код, а в .NET это просто CIL. - person John V; 12.01.2012
comment
C #, как здесь было сказано, сначала компилируется в промежуточный язык, и только после того, как компилируется в машинно-ориентированный машинный код. Есть причина проверить ответ Эрика Липперта stackoverflow.com/questions/7875253/, чтобы понять причины этого. - person Tigran; 12.01.2012