Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Что возможно в IL чего нельзя сделать на языке высокого уровня .NET?

#net


В общем, задался этим вопрос из-за этого ответа по другому вопросу.

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

(Так ли это?)

Получается, что я могу взять IL-код, полученный после компиляции на C# и добавить
в него какое-нибудь экзотическое поведение(Которое не запрещено в IL), которого нельзя
добиться языком высокого уровня, скомпилировать и подключить эту сборку к проекту и
прозрачно использовать на каком-нибудь C# ?

Собственно, интересует вопрос, на сколько все дозволено в IL и возможные побочные
эффекты у пользователей таких либ.
    


Ответы

Ответ 1



Возможности IL несколько шире возможностей C#, например можно распаковывать объекты по ссылке: ldarg_0 unbox [mscorlib]System.Int32 ldc.i4 42 stobj [mscorlib]System.Int32 ret Вот к чему такое приводит: object obj = -1; Foo(obj); Console.WriteLine(obj); // 42 Однако, большинство ограничений C# и IL - общие: язык C#, особенно в последних версиях, позволяет очень многое из того что позволяется средой выполнения. И да, просто так обращаться к приватным полям в IL - нельзя. На самом деле, в приведенном вами примере обращение к приватному полю стало возможным не только из-за того что это IL, но еще и из-за того что использовался динамический метод. Динамические методы могут обходить проверки видимости если у создавшего их кода достаточно привилегий (и обход проверок был включён для этого метода параметром конструктора)

Ответ 2



В il-коде можно помечать функции как экспортируемые, которые можно будет вызывать из нативного (не дотнетного) кода. Судя по всему, сам MS эту возможность вообще не афиширует. В компиляторы C# и VB.NET они эту фичу точно не добавили, про плюсы не в курсе.

Ответ 3



Используя IL можно выполнять CLR-команды https://en.wikipedia.org/wiki/List_of_CIL_instructions в любом порядке, каком захочется. Можно даже нарушать safe-концепцию и т п. не запрещено. Рефлексия сама по-себе позволяет получить доступ и к приватным и к другим членам класса. А IL - это язык команд. Можно создать как хорошо-оптимизированый IL-код, так и код который поломает приложение. Но что важно, что IL-код не может существовать "сам по себе", он оформляется как сборка. Это свойство используется для генерации Entity, например. Код вида foreach (PropertyInfo prop in obj.Props) do_something На IL можно через цикл реализовать можно так (условно) https://subscribe.ru/archive/comp.soft.prog.csharplessons/200703/21001224.html/ ldarg.1 getprop a do_something ldarg.1 getprop b do_something Но нужно понимать, что для даного il (который генерируете не вы, а ваш автомат) foreach (PropertyInfo prop in obj.Props) { il.Emit(OpCodes.ldarg1); //.... } нужно создать сборку, если используется динамический assembly - то будет создана временная сборка (темповый файл с dll). О быстродействии, компиляция IL занимает время (если использовать динамическое формирование IL кода), если механизм будет использован 1 раз - ускорения не будет. Если у вас миллион вызовов по свойствам (такое часто в СУБД) - то лучше создать сборку. Потому что для доступа через привычную рефлексию (foreach, Properties, SetValue) используется в 10-20 раз больше IL-команд чем просто через IL (три команды ldarg,ldarg,setprop плюс минус). Есть либы, которое это делают автоматом. Вообщем IL позволяет делать самомодифицирующийся(условно) код, или компилировать код неприбегая к "csc.exe". Если цель - получить доступ к приватному свойству - то оно чаще всего доступно просто через рефлексию.

Комментариев нет:

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