Metanit

Алан-э-Дейл       11.09.2023 г.

Оглавление

Структуры

Последнее обновление: 16.09.2019

Наряду с классами структуры представляют еще один способ создания собственных типов данных в C#. Более того многие примитивные типы, например,
int, double и т.д., по сути являются структурами.

Например, определим структуру, которая представляет человека:

struct User
{
	public string name;
	public int age;

	public void DisplayInfo()
	{
		Console.WriteLine($"Name: {name}  Age: {age}");
	}
}

Как и классы, структуры могут хранить состояние в виде переменных и определять поведение в виде методов. Так, в данном случае
определены две переменные — name и age для хранения соответственно имени и возраста человека и метод DisplayInfo для вывода информации о человеке.

Используем эту структуру в программе:

using System;

namespace HelloApp
{ 
    struct User
    {
        public string name;
        public int age;

        public void DisplayInfo()
        {
            Console.WriteLine($"Name: {name}  Age: {age}");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            User tom;
            tom.name = "Tom";
            tom.age = 34;
            tom.DisplayInfo();
			
            Console.ReadKey();
        }
    }
}

В данном случае создается объект tom. У него устанавливаются значения глобальных переменных, и затем выводится
информация о нем.

Конструкторы структуры

Как и класс, структура может определять конструкторы. Но в отличие от класса нам не обязательно вызывать конструктор для создания объекта структуры:

User tom;

Однако если мы таким образом создаем объект структуры, то обязательно надо проинициализировать все поля (глобальные переменные) структуры перед получением
их значений или перед вызовом методов структуры. То есть, например, в следующем случае мы получим ошибку, так как обращение к полям и методам происходит
до присвоения им начальных значений:

User tom;
int x = tom.age;	// Ошибка
tom.DisplayInfo();	// Ошибка

Также мы можем использовать для создания структуры конструктор без параметров, который есть в структуре по умолчанию и при вызове которого полям структуры будет
присвоено значение по умолчанию (например, для числовых типов это число 0):

User tom = new User();
tom.DisplayInfo();	// Name:   Age: 0

Обратите внимание, что при использовании конструктора по умолчанию нам не надо явным образом иницилизировать поля структуры. Также мы можем определить свои конструкторы

Например, изменим структуру User:

Также мы можем определить свои конструкторы. Например, изменим структуру User:

using System;

namespace HelloApp
{
    struct User
    {
        public string name;
        public int age;
        public User(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
        public void DisplayInfo()
        {
            Console.WriteLine($"Name: {name}  Age: {age}");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            User tom = new User("Tom", 34);
            tom.DisplayInfo();

            User bob = new User();
            bob.DisplayInfo();
			
            Console.ReadKey();
        }
    }
}

Важно учитывать, что если мы определяем конструктор в структуре, то он должен инициализировать все поля структуры, как в данном случае устанавливаются
значения для переменных name и age. Также, как и для класса, можно использовать инициализатор для создания структуры:

Также, как и для класса, можно использовать инициализатор для создания структуры:

User person = new User { name = "Sam", age = 31 };

Но в отличие от класса нельзя инициализировать поля структуры напрямую при их объявлении, например, следующим образом:

struct User
{
	public string name = "Sam";		// ! Ошибка
	public int age = 23;			// ! Ошибка
	public void DisplayInfo()
	{
		Console.WriteLine($"Name: {name}  Age: {age}");
	}
}

НазадВперед

Коллекция Dictionary

Последнее обновление: 31.10.2015

Еще один распространенный тип коллекции представляют словари. Словарь хранит объекты, которые представляют пару ключ-значение.
Каждый такой объект является объектом структуры KeyValuePair<TKey, TValue>. Благодаря свойствам и
, которые есть у данной структуры, мы можем получить ключ и значение элемента в словаре.

Рассмотрим на примере использование словарей:

Dictionary<int, string> countries = new Dictionary<int, string>(5);
countries.Add(1, "Russia");
countries.Add(3, "Great Britain");
countries.Add(2, "USA");
countries.Add(4, "France");
countries.Add(5, "China");          

foreach (KeyValuePair<int, string> keyValue in countries)
{
    Console.WriteLine(keyValue.Key + " - " + keyValue.Value);
}

// получение элемента по ключу
string country = countries;
// изменение объекта
countries = "Spain";
// удаление по ключу
countries.Remove(2);

Класс словарей также, как и другие коллекции, предоставляет методы Add и Remove для добавления и удаления элементов.
Только в случае словарей в метод Add передаются два параметра: ключ и значение. А метод Remove удаляет не по индексу, а по ключу.

Так как в нашем примере ключами является объекты типа , а значениями — объекты типа , то словарь
в нашем случае будет хранить объекты . В цикле мы их можем получить и извлечь
из них ключ и значение.

Кроме того, мы можем получить отдельно коллекции ключей и значений словаря:

Dictionary<char, Person> people = new Dictionary<char, Person>();
people.Add('b', new Person() { Name = "Bill" });
people.Add('t', new Person() { Name = "Tom" }); 
people.Add('j', new Person() { Name = "John" });

foreach (KeyValuePair<char, Person> keyValue in people)
{
	// keyValue.Value представляет класс Person
    Console.WriteLine(keyValue.Key + " - " + keyValue.Value.Name); 
}

// перебор ключей
foreach (char c in people.Keys)
{
    Console.WriteLine(c);
}

// перебор по значениям
foreach (Person p in people.Values)
{
    Console.WriteLine(p.Name);
}

Здесь в качестве ключей выступают объекты типа , а значениями — объекты . Используя свойство
, мы можем получить ключи словаря, а свойство соответственно хранит все значения в словаре.

Для добавления необязательно применять метод , можно использовать сокращенный вариант:

Dictionary<char, Person> people = new Dictionary<char, Person>();
people.Add('b', new Person() { Name = "Bill" });
people = new Person() { Name = "Alice" };

Несмотря на то, что изначально в словаре нет ключа ‘a’ и соответствующего ему элемента, то он все равно будет установлен. Если же он есть, то
элемент по ключу ‘a’ будет заменен на новый объект

Инициализация словарей

В C# 5.0 мы могли инициализировать словари следующим образом:

Dictionary<string, string> countries = new Dictionary<string, string>
{
    {"Франция", "Париж"},
    {"Германия", "Берлин"},
    {"Великобритания", "Лондон"}
};

foreach(var pair in countries)
    Console.WriteLine("{0} - {1}", pair.Key, pair.Value);
            

То начиная с C# 6.0 доступен также еще один способ инициализации:

Dictionary<string, string> countries = new Dictionary<string, string>
{
    = "Париж",
    = "Берлин",
    = "Лондон"
};       

НазадВперед

Язык программирования C

Последнее обновление: 18.05.2017

Язык программирования С (си) является одним из самых популярных и распространенных языков. Он представляет компилируемый язык программирования
общего назначения со статической типизацией, разработанный в 1969—1973 годах в компании Bell Labs программистом Деннисом Ритчи (Dennis Ritchie).

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

Первоначально язык С предназначался для написания операционной системы Unix. Впоследствии Си стал одним из популярных языков, а его основной
сферой применения стало системное программирование, в частности, создание операционных систем, драйверов, различных утилит, антивирусов и т.д.
К слову сказать, Linux большей частью написан на Си. Однако только системным программированием применение данного языка не ограничивается. Данный язык можно использовать в программах любого уровня, где важны скорость работы и
производительность. Так, мы можем писать с помощью Си и прикладные приложения, и даже веб-сайты (используя технологию CGI — Common Gateway Interface). Но,
конечно, для создания графического интерфейса и веб-приложений, как правило, выбираются более подходящие инструменты и технологии, но тем не менее круг
использования Си довольно широк. Это в немалой степени определило популярность языка. Например, в известном рейтинге языков программирования TIOBE язык С
долгое время уверенно удерживает второе место.

Несмотря на большие возможности язык Си одновременно довольно прост. Он не содержит много конструкций, библиотек, его легко осваивать и изучать. Поэтому нередко его выбирают в качестве
языка для изучения в целом программированию.

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

Развитие Си оказало большое влияние в целом на развитие языков программирования. В частности, его синтаксис стал основой для таких языков как
С++, С#, Java, PHP, JavaScript. Особо следует сказать про связь с C++. C++ напрямую произошёл от Си. Но впоследствии их
развитие происходило отдельно друг от друга, и даже появилась несовместимость между ними. Стандарт C99 добавил в язык Си ряд конфликтующих с C++ особенностей. В итоге в настоящее время
оба языка являются фактически самодостаточными и развиваются независимо.

Основные особенности Си

  • Универсальность — один и тот же код может быть скомпилирован на почти каждой платформе (при наличии для нее компилятора)

  • Высокая скорость выполнения

  • Компактность, небольшой размер выходных скомпилированных файлов

Основные этапы развития

В 1978 году Брайан Керниган и Деннис Ритчи опубликовали первое издание своего знаменитого труда «Язык программирования Си». Долгое время эта книга
служила неформальной спецификацией языка Си. Однако быстрое распространение Си привело к необходимости выработки общих стандартов.
И в 1983 году организация ANSI (Американский национальный институт стандартов) создала комитет для разработки спецификации Си.
А в 1989 году спецификация была утверждена. Эту версию языка принято называть ANSI C или C89.
В 1990 году спецификация ANSI C была немного дополнена Международной организацией по стандартизации (ISO). Новый стандарт стал называться ISO/IEC 9899:1990 или сокращенно С90.

В конце 1990-х годов стандарт подвергся пересмотру, что привело к выходу нового стандарта в 1999 году, который принято называть C99 (официальное название ISO 9899:1999).

И в декабре 2011 был опубликован новый и последний на данный момент стандарт для языка Си — С11 (официальное название ISO/IEC 9899:2011).

Вперед

Что такое F#

Последнее обновление: 14.07.2021

F# (F Sharp или Эф шарп) — это функциональный статически типизированный язык программирования общего пользования, который создан и развивается компанией Microsoft и который предназначен для широкого круга задач.

Отличительной чертой F# является то, что он работает поверх платформы .NET и тем самым позволяет в
определенной степени использовать возможности, предоставляемые этой платформой, например, систему типов, систему сборки мусора и т.д. Это также означает, что при компиляции
код на F# компилируется в промежуточный язык IL (Intermediate Language), понятный для платформы .NET. И при запуске .NET управляет
выполнением этого приложения.

Кроме того, благодаря этому мы можем в проекте на F# использовать вспомогательные библиотеки, написанные с помощью других .NET-языков (например,
на C# или VB.NET). Подобным образом мы можем на F# написать библиотеку и затем подключить ее в проекты на других .NET-языках.

F# кроссплатформенный, не привязанный к определенной операционной системе, на нем можно разрабатывать на Windows, MacOS и Linux.

F# — достаточно зрелый язык программирования. Его первая версия вышла в мае 2005 года. Последней версией на данный момент является F# 5.0,
которая вышла в ноябре 2020 года вместе с .NET 5.0.

Для разработки на F# необходимо установить .NET SDK. Для написания кода можно выбрать любой текстовый редактор, а компилировать приложения в консоли. Однако для упрощения разработки
на Windows также можно использовать такую бесплатную среду разработки как Visual Studio от Microsoft, которая имеет полноценную поддержку работы с данным языком и
необходимые шаблоны проектов. Под MacOS есть бесплатный аналог — Visual Studio for Mac

В качестве альтернативы также можно выбрать другую — платную среду разработки — Rider от компании JetBrains, которая также имеет поддержку F# и которая работает, как на Windows, так и на MacOS и Linux.

F# позволяет создавать самые разные приложения — простые консольные приложения, серверные веб-приложения, веб-сервисы,
десктопные и мобильные приложения. Стоит отметить, что кроме тех типов проектов, которые поддерживаются .NET SDK и Visual Studio по умолчанию,
есть куча проектов, которые позволяют использовать F# для создания других типов приложений. Например, проект Fable позволяет компилировать код
F# в код JavaScript и тем самым писать на F# браузерные (клиентские) веб-приложения.

НазадВперед

Фреймворк Moq

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 31.10.2015

Кроме собственно фреймворков для создания и проведения юнит-тестов при тестировании часто бывают полезны такие фреймворки, которые
позволяют имитировать или эмулировать какую-то функциональность или создавать мок-объекты. Подобных фреймворков существует множество,
и одним из самых популярных является Moq.

Итак, возьмем проект из прошлой темы и подключим Moq через NuGet в проект тестов (а не в проект веб-приложения):

После этого в узел References проекта тестов будет добавлена библиотека Moq, содержащая всю основную функциональность.

Теперь изменим класс тестов следующим образом:

using Moq;
.................


public class HomeControllerTest
{
    
    public void IndexViewModelNotNull()
    {
        // Arrange
        var mock = new Mock<IRepository>();
        mock.Setup(a => a.GetComputerList()).Returns(new List<Computer>());
        HomeController controller = new HomeController(mock.Object);

        // Act
        ViewResult result = controller.Index() as ViewResult;

        // Assert
        Assert.IsNotNull(result.Model);
    }  
}

Для доступа к функциональности Moq вначале подключается соответствующее пространство имен .

Moq предназначен для имитации объектов. В данном случае имитируется функциональность репозитория. Для этого объект Mock типизируется
соответствующим типом:

Затем выполняется настройка mock объекта с помощью метода . Так как нам надо имитировать возвращение методом
набора объектов, то данный метод вызывается в методе Setup, а с помощью метода определяем данный набор объектов.

Поскольку контроллер HomeController теперь в конструкторе принимает объект репозитория, то мы можем передать в конструктор мок-объект, который имитирует функциональность
репозитория:

Теперь запустим тест. Он должен завершиться неудачей, так как у нас не передается в методе Index в представление никакой модели. Поэтому изменим метод
Index:

public ActionResult Index()
{
    var model = repo.GetComputerList();
    return View(model);
}

И если мы сейчас запустим тест, то он пройдет успешно.

Теперь для примера добавим в класс тестов еще один метод:


public void IndexViewBagMessage()
{
    // Arrange
    var mock = new Mock<IRepository>();
    mock.Setup(a => a.GetComputerList()).Returns(new List<Computer>() { new Computer()});
    HomeController controller = new HomeController(mock.Object);
    string expected = "В базе данных 1 объект";

    // Act
    ViewResult result = controller.Index() as ViewResult;
    string actual = result.ViewBag.Message as string;

    // Assert
    Assert.AreEqual(expected, actual);
} 

Цель данного метода — проверить сообщение, передаваемое через ViewBag. Причем я хочу, чтобы сообщение передавалось, если
в базе данных больше 0 объектов. Для этого список, возвращаемый методом , инициализируется одним объектом. А
метод проверяет оба сообщения.

Запустим тест и увидим, что он завершился неудачей. Теперь нам надо изменить метод Index в главном проекте, чтобы он соответствовал тесту:

public ActionResult Index()
{
    var model = repo.GetComputerList();
	if (model.Count > 0)
        ViewBag.Message = String.Format("В базе данных {0} объект", model.Count);
    return View(model);
}

Поскольку с помощью Moq мы имитировали в методе контроллера список с одним элементом, то если мы сейчас запустим тест, то он пройдет успешно, так как
строка в тесте и значение ViewBag.Message будут совпадать.

НазадВперед

Гость форума
От: admin

Эта тема закрыта для публикации ответов.