Comments 61
Ограничений U# в конструкциях языка оказалось немного – это атавизмы goto и case goto, а также yield, не моделируемый адекватно в автоматическом режиме. Не рекомендуется (хотя и можно) использовать struct, есть нюансы с наименованиями – всё это подробно описывается в отдельном документе.
Рискую нарваться на негатив (т.к. не специалист), но yield
и struct
это вообще ключевые ключевые слова (keywords) в языке. yield
может быть незаменим при работе с коллекциями т.к. без него не написать iterator methods. А без struct
я даже не знаю. Я даже не говорю про всякие ништяки типа ref struct
, unsafe
. Не уверен что есть 1-к-1 соответствие в Java
, а в Python
тем более.
Как вишенка на торте — сегодня долго возился с кастомным аттрибутом, наболело, поэтому обратил внимание, — согласно документации класс Attribute
не поддерживается, в Type
только 4 элемента, что фактически значит что рефлексии нет (без понятия как это работает в Java
, полагаю там должен быть аналог, про Python
из-за отсутствия статической типизации — вообще хз).
Фактически реализована трансляция каких-то совсем базовых методов базовых типов в аналогичные на другом языке (читай правка синтаксиса). Я прекрасно понимаю аргумент simplified English, но таким способом достаточно сложный проект транслировать невозможно.
Вообще не понятно зачем транслировать в Python
так как языки ну совсем разного класса. Java
еще я могу понять, и то проблем куча.
Конечно я допускаю, что я абсолютно не прав, так как упустил какие-то важные пункты или просто не вижу кейсов, в которых это могло бы быть полезно.
2. struct — в документации я подробно описал, что их не запрещено использовать, они переводятся в class, но есть нюансы при присваиваниях. Немного помучившись, в своём проекте я вообще отказался от struct. И что удивительно, на скорость выполнения это никак не повлияло, а я думал, что их использования в моём случае даст выигрыш. Так что можно использовать.
3. Атрибуты не поддерживаются (игнорируются) — ну да, чем то придётся пожертвовать
4. Reflection есть в небольшом объёме, который требуется мне (получить тип объекта, для типа список конструкторов, вызвать конструктор). Но этот список расширяем путём внешних настроек. Невозможно сразу съесть слона (системные классы). Помогите нам — выберите какую-нибудь полезную функцию C#, найдите аналог в Java и опишите.
Да, приходится за всё платить, и мне для кросспрограммируемости в своём проекте Pullenti пришлось кое что переделать. Например, отказаться от плагинного способа загрузки dll с анализаторами обработки текста. Но это мелочи.
Хотел посмотреть на ваш проект, но исходников открытых я так понимаю нет. Судя по тому, что я понял из демонстрационного проекта, в случае Pullenti
описанного функционала U#
должно хватить, а вот насчет более сложных (в смысле применяемых технологий) проектов — я не уверен.
Для меня больной темой например оказались аттрибуты и yield
, т.к. существует огромная разница между
IEnumerable<T> YieldMethod<T>(/*...*/) {yield break;}
и аналогичному ему
List<T> ListMethod<T>(/*...*/) {/*???*/}
Первый позволяет потреблять элементы коллекции лениво, или же являться источником бесконечного количества элементов. List<>
в свою очередь вполне себе конкретная структура данных.
Попробую привести пример:
InfiniteSourceOfInt().SomeYieldMethod().Take(5);
должен корректно отработать и в конечном счете вернуть некий IEnumerable<>
из 5 элементов. А вот если
InfiniteSourceOfInt().SomeListMethod().Take(5);
то я полагаю здесь будет бесконечный цикл т.к. SomeListMethod
должен проитерировать всю исходную коллекцию, чтобы сгенерировать List<>
, а она бесконечная (ну или очень большая, например).
Сейчас обнаружил что typeof
тоже не поддерживается, is
и as
находят свои аналоги, а вот type matching
вида var x = "a_b_c" is string s ? s.Split('_') : throw new InvalidOperationException();
уже нет. Про pattern matching
в case
блоке вообще молчу.
Прошу прощения, если это звучит негативно, мне оказалось довольно любопытно разобраться как работает ваш транслятор. Summary моих комментариев можно свести к следующему:
Ограничений U# в конструкциях языка оказалось немного
на самом деле ограничений довольно много, и мне сложно представить как я бы писал U#
-совместимый код.
P.S.: вовремя обновил страницу и увидел комментарий Vadem ниже
async/await, похоже, тоже не поддерживается.
А вот это уже критично.
В списке либ отсутствует Task
, что ставит под вопрос трансляцию кода даже с малой долей параллелизма — фактически при текущих ограничениях любые длительные операции (обращение к БД, вычисления, веб реквесты), которые занимают какое то реальное, ощутимое время, транслировать невозможно. А это действительно минус, увы.
2. Раз struct безусловно переделывается в класс, означает ли это что default(T) работает некорректно? Это достаточно важно, так как и решарпер, и ms code analysis просит убрать ненужную проверку на null в структурах, так как там в принципе не может быть null, а без правильно работающего default, отсутствие null гарантировать уже сложнее
2. default(T) для структур в Java преобразуется в new T(). Он во основном нормально работает, но если где то встретилось a = b для структуры, а потом поменялись поля b, то у а они тоже поменяются, так как для классов это один объект. Если таких ситуаций нет или делать a = new(b) (кстати, вроде UniSharping такие ситуации пытается отслеживать вызывать new, я уже не помню — отказался от структур), то всё будет работать.
Можно взять Bridge.NET, скомпилировать C# в JavaScript, а уже его заэмбеддить в Java/Python. Есть большое подозрение, что процесс будет менее болезненным, чем применение представленного транслятора. Ибо у Bridge.NET полная поддержка самого C#, включая семантику структур, а портированный на JS набор класс BCL достаточно богатый, да и рефлексия работает целиком (хоть и увеличивает размер бандла, если её включить).
Ограничений U# в конструкциях языка оказалось немного – это атавизмы goto и case goto, а также yield, не моделируемый адекватно в автоматическом режиме.
async/await
, похоже, тоже не поддерживается.А вот это уже критично.
Просто, кажется, что async/await — это одна из самых важных фич в C# на данный момент.
В Python, кстати, она тоже есть.
Проще работать с байткодом CLR, чем с исходниками.
async/await и прочие новые возможности языка являются сахаром и в MSIL не существует.
Бонусом пойдет поддержка других .NET языков
Главное чтобы в итоге из кода на C# получался адекватный код на других яызках.
И AST как раз в этом плане работать гораздо проще чем с MSIL.
> атавизмы goto и case goto,
Конечные автоматы — бай-бай.
> а также yield, не моделируемый адекватно в автоматическом режиме.
Грусть-печаль… Работа с коллекциями, до скорых встреч.
> Не рекомендуется (хотя и можно) использовать struct,
Прощай быстродействие.
Если цель получить в результате конверсии СПО, то миграция с языка C# (с лицензией MIT) на Python (имеющий более ограниченный по сравнению с MIT лицензию BSD) или на Java (вирусная GPL или проприеритарная JCP) выглядит довольно непоследовательно.
А что ещё более непоследовательно, так это использовать проприетарный тул для этого с закрытыми исходниками и с непонятной лицензией.
система бесплатна для некоммерческого использования?
Интересно, Вы в ресторане, скажем, просите официанта принести исходный продукт для его потребления? А то вдруг повар там что от себя лишнего добавит, а так всегда можно самому скомпилировать блюдо, или вдруг повар пропадёт и не сможет внести изменение, ищи его потом свищи… А автомобиль — с описанием технологии, вдруг потребуется что-нибудь исправить.
У меня в профиле есть ссылка на GitHub профиль. Можете сами посмотреть.
А сам UniSharping написан на C#? Может ли его исходный код быть конвертирован в Java или Python?
UniSharping: конвертирование кода C# в Java и Python