В этом выпуске:
Раздел: Каждый кто пишет код.
- Вопрос #4: Какая разница между исполняемым EXE-фалом и библиотекой динамической линковки DLL?
- Вопрос #5: Чем строгая типизация отличается от нестрогой типизации? Какая предпочтительнее? Почему?
- Вопрос #6: Некий продукт является “Component Container”. Назовите хотя бы 3 компонента семейства Windows Server которые можно называть “Component Container”.
Вопрос #4: Какая разница между исполняемым EXE-фалом и библиотекой динамической линковки DLL?
Овтет: Оговорюсь сразу, основные различия между exe и dll буду рассматривать в рамках .NET. Для начала расшифруем названия, дабы было все ясно: exe-сокращение от executable, т.е. исполняемый файл; dll – сокращение от dynamic linked library, т.е. динамически линкуемая библиотека. Получается, что exe мы выполняем и в процессе используем некие методы или типы из динамической библиотеки. С точки зрения кодирования в случае исполняемого фала необходимо наличие единственной “точки входа”. В коде это реализуется обязательным public static методом Main, который в качестве параметров, например, может брать массив строк, содержащий параметры командной строки. При создании динамической библиотеки, мы вообще можем не задумываться о “точке входа”. По сути это просто набор классов, интерфейсов, структур и т.п. необходимых нам для структурирования ПО. С точки зрения внутренней структуры файла, то исполняемый файл от библиотеки можно отличить например по PE-заголовку.
Вопрос #5: Чем строгая типизация отличается от нестрогой типизации? Какая предпочтительнее? Почему?
Ответ: Для начала рассмотрим основные различия между сильной и слабой типизацией. Прежде всего, слабая типизация предполагает неявное вычисление/преобразование типов и/или ad hoc (это слово я сам не рискую переводить и толкового перевода ещё не встречал) полиморфизм. При сильной или строгой типизации все типы известны заранее, и преобразование проходит по заранее установленным строгим правилам. Строгим, понятно, по отношению к правилам принятым при слабой типизации. Классическим примером слабой типизации является, например, присвоение значения переменной в языке TCL. С одной стороны мы можем написать:
set myVal "Hello world!"
myVal – строка
с другой стороны можно написать так:
set myVal [file dirname [file dirname $curentdir]]
maVal – путь
Или, делая так:
set myVal {}
А потом в цикле так:
lappend myVal @someItemв myVal получим список.
Таким образом, тип переменной вычисляется на момент выполнения присвоения ей некого значения.
Сильную (строгую) типизацию, представляет язык C#. Если раньше в C++ мы могли написать:
MyObj* m_pObj = GenerateMyObj(); if(!m_pObj) return -1;
То уже в C# такое преобразование типов не пройдёт, тут будь добр делать все явно:
MyObj m_pObj = GenerateMyObj(); if(m_pObj == null) return -1;
В этой разновидности типизации для присвоения переменной некоторого значения мы должны сначала объявить эту переменную и задать ей тип. Т.е. основное отличие от слабой типизации в том, что на момент компиляции все типы должны быть известны. Так же, не может быть речи не о каком ad hoc полиморфизме. Например в случае функционального полиморфизма операция сложения, определённая для целочисленных типов, при использовании со строками просто вызовет ошибку компиляции.
На вопрос что лучше, понятно, однозначный ответ получить сложно. Мне по духу ближе сильная динамическая типизация, однако и в слабой есть свои плюсы, язык с такой системой типов более гибкий. Однако у строгой типизации, как мне кажется, есть одно неоспоримое преимущество, такой код чаще, банально, надёжнее. Использование операторов кастования as или is в C#, сводит появления исключительной ситуации практически на нуль. Однако речь идёт о компилируемых языках, для интерпретируемых слабая типизация оказывается удобнее и прозрачнее.
Вопрос #6: Некий продукт является “Component Container”. Назовите хотя бы 3 компонента семейства Windows Server которые можно называть “Component Container”.
Ответ: Начнём со строгих определений в рамках .NET. Контейнером называется объект, реализующий интерфейс System.ComponentModel.IСontainer или наследующийся от класса реализующего этот интерфейс, и, содержащий нуль или более компонентов. В свою очередь, компонентом называется объект, реализующий интерфейс Systerm.ComponentModel.IСomponent или наследующийся от класса, реализующего этот интерфейс, предназначенный для повторного использования и взаимодействия с другими объектами.
Самое важное, это то, что компонентом является объект, который мы можем повторно использовать. Воплощение идеи объектно-ориентированного программирования. Зачем нам писать что-то свое, когда мы можем использовать уже написанный, оттестированный и отлаженный компонент? По сути, реализации интерфейсов IComponent и IContainer необходимы для более грамотного и удобного обращения с компонентами. Любой графический контрол тоже компонент, который описывает пользовательский интерфейс. Т.е .компонент с визуальным представлением.
Что же касается примеров, возьмем основные контейнеры: System.Windows.Forms.Form, System.Windows.Forms.UserControl и, например, System.Windows.Forms.PrpertyGrid.




.png)