Подтвердить что ты не робот

Что такое "непроверяемый код" и почему это плохо?

Я разрабатываю вспомогательный метод, который делает ленивую загрузку определенных объектов для меня, вызывающ это выглядит следующим образом:

public override EDC2_ORM.Customer Customer {
    get { return LazyLoader.Get<EDC2_ORM.Customer>(
            CustomerId, _customerDao, ()=>base.Customer, (x)=>Customer = x); }
    set { base.Customer = value; }
}

когда я компилирую этот код, я получаю следующее предупреждение:

Предупреждение 5 Доступ к члену 'EDC2_ORM.Billing.Contract.Site' через ключевое слово "base" из анонимный метод, лямбда-выражение, выражение запроса или результаты итератора в непроверяемом коде. Рассмотрим перемещение доступ к вспомогательному методу на содержащий тип.

Что такое жалоба здесь и почему я плохо себя чувствую?

4b9b3361

Ответ 1

"base.Foo" для виртуального метода сделает не виртуальный вызов родительского определения метода "Foo". Начиная с CLR 2.0, CLR решила, что не виртуальный вызов по виртуальному методу может быть потенциальным ядром безопасности и ограничить сценарии, в которых они могут использоваться. Они ограничили это тем, что делали не виртуальные вызовы виртуальных методов в рамках одной и той же иерархии классов.

Лямбда-выражения помещают в этот процесс излом. Лямбда-выражения часто создают замыкание под капотом, которое является полностью отдельным классом. Таким образом, код base.Foo в конечном итоге станет выражением в совершенно новом классе. Это создает исключение проверки с CLR. Следовательно, С# выдает предупреждение.

Боковое примечание: эквивалентный код будет работать в VB. В VB для не виртуальных вызовов виртуального метода в исходном классе будет создан метод stub. В этом методе будет выполнен не виртуальный вызов. "Base.Foo" будет перенаправлен в "StubBaseFoo" (сгенерированное имя отличается).

Ответ 2

Я подозреваю, что проблема в том, что вы в основном говорите: "Я не хочу использовать самую производную реализацию Клиента - я хочу использовать эту конкретную" - что вы не сможете сделать нормально. Вам разрешено делать это в производном классе и по уважительным причинам, но из других типов вы будете нарушать инкапсуляцию.

Теперь, когда вы используете анонимный метод, выражение лямбда, выражение запроса (которое в основном использует лямбда-выражения) или блок итератора, иногда компилятор должен создать для вас новый класс за кулисами. Иногда это может уйти от создания нового метода в одном типе для лямбда-выражений, но это зависит от контекста. В принципе, если какие-либо локальные переменные захватываются в выражении лямбда, для этого нужен новый класс (или действительно несколько классов, в зависимости от сферы действия - он может стать неприятным). Если выражение лямбда только фиксирует ссылку this, для логики выражения лямбда может быть создан новый метод экземпляра. Если ничего не зафиксировано, статический метод в порядке.

Итак, хотя компилятор С# знает, что на самом деле вы не нарушаете инкапсуляцию, CLR не делает - поэтому он рассматривает код с некоторым подозрением. Если вы работаете под полным доверием, это, вероятно, не проблема, но под другими уровнями доверия (я не знаю деталей небрежно) ваш код не будет запущен.

Помогает ли это?

Ответ 3

скопировать/вставить из здесь:

Codesta: С#/CLR имеет 2 типа кода, безопасный и небезопасный. Что он пытается обеспечить и как это повлияло на виртуальную машину? Peter Hallam: для С# условия безопасны и небезопасны. CLR использует термины, поддающиеся проверке и не проверяемые.

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

Использование стандартных указателей стиля C создает непроверяемый код. CLR поддерживает указатели стиля C изначально. Когда у вас есть указатель стиля C, вы можете читать или записывать в любой байт памяти в процессе, поэтому среда выполнения не может обеспечить соблюдение политики безопасности. На самом деле это могло бы, но штраф за исполнение сделал бы его непрактичным.

Теперь это не полностью отвечает на ваш вопрос (т.е. ПОЧЕМУ сейчас этот непроверяемый код), но по крайней мере он объясняет, что "непроверяемым" является CLR-термин для "небезопасных". Я предполагаю, что анонимные методы и базовые классы приводят к некоторой фанковой манере указателя внутри.

Кстати: я думаю, что фрагмент кода не соответствует предупреждающему сообщению. В коде говорится о клиенте, предупреждение - о выставлении счетов. Можно ли разместить код исполнительного механизма для предупреждения? Возможно, у вас есть что-то еще в этом коде, что лучше объяснит, почему вы получаете предупреждение.