Это может быть просто мой самый длинный титул 😜. Неделя прошла хорошо. Готовлюсь к поездке в Канаду на несколько дней, а затем в Северную Индиану, чтобы увидеть семью. Не волнуйтесь, кодирование будет происходить в течение этого времени… это должно произойти… Хорошо, без лишних слов, давайте сразу приступим к чтению вопросов и ответов инструктора на этой неделе!

  1. Обсудите словами то, что вы узнали на уроке сегодня или на этой неделе.

Класс на этой неделе был об издательских услугах. Поэтому мы взяли небольшой API, создали учетные записи Azure, а затем опубликовали API в Azure App Services. Это было очень своевременно, потому что я уже смотрел несколько видео о хостинге/публикации с помощью Wordpress и Heroku. Хотя я уверен, что это может и будет становиться сложнее, то, что мы сделали до сих пор, было действительно простым и понятным.

Тем не менее, что меня интересует, так это узнать больше о стороне DevOps, в которой вы должны управлять своими собственными серверами и базами данных. Это то, чем мы немного занимаемся: размещаем серверы для компаний-разработчиков программного обеспечения или компаний, у которых есть собственные разработчики, где я сейчас работаю; но мне лично не нужно управлять тем, сколько виртуальной памяти или обработки имеет виртуальная машина (виртуальная машина) по отношению к запросам, поступающим в БД.

Кое-что также в некоторой степени связано с базами данных, но в большей степени с веб-приложениями в целом. Недавно у меня был косвенный опыт атаки методом грубой силы на страницу входа на сайт для одной из наших компаний в области медицины. Разработчик получил жалобы на то, что пользователи блокируются, потому что они не меняют свои пароли вовремя, а затем все еще пытаются использовать старый пароль слишком много раз, и поэтому они хотели, чтобы он понизил настройки безопасности. Он сдался, и почти сразу же они начали получать очень большое количество запросов на вход с двух IP-адресов за очень короткий промежуток времени. Это привело к тому, что страница входа в систему немного зависла. Он снова включил меры безопасности и заблокировал эти IP-адреса. Было просто интересно посмотреть, как на самом деле реализуются вещи, о которых мы узнали в классе, и это придает немного больше значения тому, как мы разрабатываем наши приложения в будущем.

2. Объясните разницу между стеком и кучей.

Стек и куча похожи на контейнеры для хранения. Они оба хранятся в оперативной памяти компьютера (оперативной памяти) и содержат значения или ссылки из приложения. Стек содержит такие значения, как int x = 5, тогда как куча содержит такие вещи, как строки или объекты, такие как Vehicle maroonCar = new Vehicle();

Помимо того, какие значения отслеживаются стеком и кучей, еще одно отличие состоит в том, что стек представляет собой структуру данных порядка LIFO (последним пришел — первым вышел) — отсюда и название «стек». Таким образом, когда функция объявляет переменную, она помещается в стек, а затем, когда функция «выходит», все эти переменные удаляются из стека, освобождая место для новых переменных. Центральный процессор управляет стеком, эффективно его организуя, что делает чтение и запись в него быстрыми и удобными для разработчика. Однако следует отметить, что стек, в зависимости от ОС, может содержать переменные только до определенного размера.

Куча, однако, более динамична, то есть она не следует правилу LIFO и не так тщательно управляется ЦП. Это означает, что в некоторых языках, таких как C, разработчик должен управлять кучей, явно выделяя и освобождая пространство памяти. К счастью, в C# это управление делается за нас, чтобы избежать таких вещей, как утечка памяти. Однако тот факт, что он не управляется процессором, означает, что он немного медленнее при доступе. С положительной стороны, он больше, чем стек, и не имеет ограничений на размер памяти (конечно, вы не можете превысить объем оперативной памяти компьютера). Кроме того, поскольку он не следует LIFO, к переменным, размещенным в куче, может обращаться любая функция из любой точки программы, тогда как переменные стека являются «локальными» по области видимости и доступны только той функции, которая их объявила.

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

(net-informations.com), (gribblelab.org)

3. Объясните разницу между интерфейсом и абстрактным классом в .NET.

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

Так зачем использовать абстрактный класс над интерфейсом или наоборот? Конечно, по этому вопросу ведутся споры, однако, поскольку абстрактные классы допускают реализацию, они обычно полезны для создания базы, от которой могут наследовать многие связанные объекты. Таким образом, если между объектами, такими как Shapes или Vehicles, есть что-то общее, может быть полезно определить и реализовать их общие черты в базовом абстрактном классе, при этом позволяя им иметь разные или расширенные реализации. Это можно назвать версионированием. Это также означает, что если вам нужно изменить общую функциональность для всех производных классов, вы можете внести это изменение в абстрактный класс, и подклассы автоматически реализуют изменения; это не относится к интерфейсам.

Интерфейсы больше подходят для несвязанных (или слабо связанных) объектов. Например, в проекте API, над которым я сейчас работаю, мне нужно определить ресурсы, которые будут использоваться в наших рабочих машинах на рабочих местах. В одном случае «предмет» может быть кабелем, в другом — маршрутизатором, в третьем — сервером или жестким диском. Все они используются для выполнения работы, а их общие черты — это просто такие вещи, как имя, описание, стоимость, используемое количество и т. д. Если бы я хотел создать класс, который определяет общие функции для маршрутизаторов, но при этом дает возможность расширять определенные черты и функции уникальный для бренда Mikrotik по сравнению с Meraki, то я бы, вероятно, сделал абстрактный класс. Кроме того, интерфейсы больше подходят для кратких определений функций, а абстрактные классы — для более крупных функциональных блоков.

4. Что такое делегат в .NET?

Делегат — это метод, который «указывает» на функцию или передает функцию в качестве параметра. Например:

Таким образом, метод делегата addNumbers инициализируется так, чтобы указывать на объект, вызывающий метод добавления, поэтому он принимает два целых числа и передает их методу добавления, который также принимает два целых числа. Вы можете задаться вопросом, что в этом такого замечательного. Почему бы просто не вызвать уравнение1.Добавить(10, 20)? В этом случае вы будете правы. Это довольно произвольный пример. Делегаты полезны для таких вещей, как обратные вызовы и для параметризации кода, предоставляя вам уровень абстракции, который избавляет от необходимости создавать кучу разных версий одного и того же метода. Вот пример, который мне пригодился от профессора и ютубера Джейми Кинга:

Происходит следующее: делегат с именем MeDelegate передается в качестве второго параметра метода RunNumbersThroughGauntlet. Итак, когда вызывается метод и передается массив чисел для первого параметра, а затем метод LessThanTen передается в качестве второго параметра, компилятор видит, что «перчатка» (наш делегат) принимает целочисленный параметр и затем передает его функции. это ссылка, которая в данном случае является LessThanTen. Когда метод проходит через числа в массиве, он передает их через функцию return n ‹ 10. Не делая что-то подобное (и есть способы еще больше абстрагироваться, чтобы вам не пришлось создавать кучу статических логических методов LessThan….), вам пришлось бы написать метод со своим собственным блоком foreach и оператором if для каждого другое сравнение, которое вы хотите сделать — утомительное и загромождающее.

* Помните, что делегаты отслеживают метод и цель (объект, для которого вызывается метод). Если вы в таком же замешательстве, как и я, рекомендую посмотреть серию видео Джейми Кинга о делегатах.

5. Как реализовать общее действие в WebAPI?

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

Из того, что я смог найти по этому поводу, это довольно прямолинейно, пока вы не изучите такие вещи, как динамически создаваемые маршруты, в этот момент полученная выгода может не перевесить затраты времени и потерю простоты в конце. Но вы можете создать общий репозиторий или класс контроллера, от которого происходят другие контроллеры. Это включает в себя создание методов (Get, Post, Put, Delete), которые не жестко закодированы для получения определенного типа объекта, а просто типа объекта в целом.

На сайте strathweb.com можно найти интересную статью, которая довольно глубоко раскрывает эту тему. Я рекомендую проверить это, особенно часть о динамически создаваемых контроллерах.

6. Почему нельзя указать модификаторы доступа для элементов интерфейса?

Вы не можете указывать модификаторы доступа в интерфейсах, потому что определения методов предназначены для наследования и последующей реализации другими классами. Таким образом, модификатор по умолчанию — «общедоступный». Помните, что интерфейсы предназначены для формирования контракта между интерфейсом и производным объектом. Нет смысла скрывать часть интерфейса, когда это прямо противоречит и сводит на нет функцию интерфейса.

7. System.Object — это родительский класс для всех классов .NET; Другими словами, все типы в .NET (будь то неявные, явные или созданные пользователем) являются производными от класса System.Object. Какие различные методы предоставляются производным классам/типам System.Object?

Методы, предоставляемые для получения классов/объектов:

  • Равноbool isEqual = person1.Equals(person2); — Этот метод предназначен для проверки равенства между ссылочными типами, чтобы подтвердить, что они указывают или не указывают на один и тот же объект. В случае, когда нужно сравнить равенство значений вместо равенства ссылок, метод Equals является виртуальным и, следовательно, переопределяемым.
  • ReferenceEqualsbool isEqual = Object.ReferenceEquals(person1, person2); — — Этот метод делает то же самое, что и Equals, но только работает с экземплярами объектов.
  • ToString

— — ToString предназначен для получения информации о значении и представления ее в удобочитаемом формате. Этот метод также является виртуальным и может быть переопределен.

  • GetType — Console.WriteLine(person1.GetType()); — — Использование этого метода возвращает объект Type, описывающий объект, для которого он был вызван. Этот метод полезен для таких вещей, как вызов метода с поздней привязкой и для определения типа объекта, заданного во время выполнения.
  • GetHashCode — Console.WriteLine(person1.GetHashCode()); — — Метод GetHashCode возвращает уникальный номер, связанный с каждым экземпляром объекта. Полезно отметить, что алгоритм по умолчанию не обязательно уникален, и поэтому для пользовательских типов рекомендуется переопределить метод GetHashCode и написать свой собственный.
  • MemberwiseClone — return (person1)MemberwiseClone(); — — MemberwiseClone создает поверхностную копию объекта. Это означает, что если вы вызовете этот метод для класса, он сделает копию вашего типа класса и всех типов значений/ссылок в классе. Но он не будет копировать объекты, на которые указывают эти ссылки. Этот метод не является виртуальным, и его нельзя переопределить.
  • Finalize или Destructor — ~Person(); — — Этот метод, как вы видите, начинается с тильды и называется так же, как и класс. Он предназначен для избавления от неуправляемых ресурсов. Однако использовать деструктор не очень хорошая идея, потому что он не выполняется детерминированным образом, а это означает, что вы не знаете точно, когда он выполнится. В C# лучше использовать интерфейс IDisposable, который высвобождает эти ресурсы определенным образом.

(csharp-station.com)

Хорошо, вы кодируете гончих собак, на данный момент этого достаточно. Хорошей недели. До скорой встречи.

Ура!