Using system collections generic c что это
Перейти к содержимому

Using system collections generic c что это

  • автор:

System.Collections.Generic.List`1

Видел статью с таким же вопросом на англ стаке, но не понял, как это применить у себя в коде, а на ру не нашёл ничего, что помогло б.

  1. Обязательно ли задавать Name или Surname как параметр, нельзя задать просто текстовое значение, как прописано у меня в коде?
using System; using System.Collections.Generic; using System.Linq; namespace arrayfiltr < class Object < public string Name < get; set; >public string Surname < get; set; >public static List Objects = new List < new Object < Name="Ivan", Surname="Ivanov">, new Object < Name="Petr", Surname="Petrov">, new Object < Name="Vasiliy", Surname="Vasiliev">>; > class Program : Object < public static void Main(string[] args) < Filtr(Objects,"Ivan"); >static void Filtr(List Objects, string Name) < ListnewObjects = new List < >; var selectedObject = from Object in Objects where Object.Name == Name select Object; foreach (Object Object in selectedObject) newObjects.Add(Object); Console.WriteLine(newObjects); > > > 

Как работать с обобщениями (generics) в C#: краткий гайд

Обобщения — конструкции языка программирования C#, позволяющие писать код, который будет одинаково работать с различными типами данных с сохранением строгой типизации языка.

Інтенсивний курс від laba: Product management.
Від ідеї до успішного продукту.

Преимущество использования обобщений — в возможности избежать упаковки и распаковки значимых типов. Это позволяет увеличить производительность кода. Также благодаря обобщениям код можно использовать повторно. Нет необходимости писать свой собственный код для каждого типа данных, не нужно использовать перегрузку методов и писать отдельный классы для типов данных. С generics в C# намного меньше шансов получить какие-либо ошибки, поскольку код лежит в одном конкретном месте программы.

«О, нет! Дженерики»

«О, нет! Обобщения»

Содержание статьи

Потужний курс від skvot: blender.
Відкрийте для себе світ 3D-графіки.
Освітній курс від laba: Delivery Manager.
Ведіть проекти до успішної доставки.

Обобщенное значение по умолчанию

Получить обобщенное значение по умолчанию для параметра типа можно благодаря использованию ключевого слова default . Случаются ситуации, когда нужно присвоить переменным универсальные параметры начальных значений и даже null . Поскольку напрямую присвоить значение нельзя, используется оператор default(T) . С его помощью мы можем присвоить типам значений 0 (обнуление полей типа), а ссылочным типам — значение null .

class Account < T style="font-weight: 400;">Статические поля generic-классов 

Статические поля практически всегда уникальны для отдельно взятого закрытого типа:

class Bob  < public static int Count; >. Console.WriteLine (++Bob.Count); // 1 Console.WriteLine (++Bob.Count); // 2 Console.WriteLine (++Bob.Count); // 1 Console.WriteLine (++Bob.Count); // 1

Создается свой набор статических членов при типизации класса. Не существует единого статического поля для объектов разных типов. В них создаются копии статического поля.

Если вы хотите, чтобы статическое поле было общим для всех типов, необходимо определить базовый класс, где будут храниться все ваши статические члены, а после установить свой generic-тип, чтобы он наследовался от базового класса.

Пример несовместимости кода:

class LengthLimitedSingletonCollection where T : new() < protected const int MaxAllowedLength = 5; protected static Dictionaryinstances = new Dictionary(); // Noncompliant public static T GetInstance() < object instance; if (!instances.TryGetValue(typeof(T), out instance)) < if (instances.Count >= MaxAllowedLength) < throw new Exception(); >instance = new T(); instances.Add(typeof(T), instance); > return (T)instance; >

Пример совместимости кода:

public class SingletonCollectionBase < protected static Dictionaryinstances = new Dictionary(); > public class LengthLimitedSingletonCollection : SingletonCollectionBase where T : new() < protected const int MaxAllowedLength = 5; public static T GetInstance() < object instance; if (!instances.TryGetValue(typeof(T), out instance)) < if (instances.Count >= MaxAllowedLength) < throw new Exception(); >instance = new T(); instances.Add(typeof(T), instance); > return (T)instance; > >

Исключения

Параметр типа статический член не используется с закрытыми типами:

public class Cache  < private static DictionaryCacheDictionary < get; set; >// Compliant >

Использование нескольких универсальных параметров

Как и для методов, обобщения могут использовать более одного типа параметров. Чтобы это осуществить, в операторе <> универсальные типы нужно ввести через запятую:

Захоплюючий курс від laba: HR-менеджер.
Розвивайте персонал і підтримуйте бізнес.
public class Exercise

class Transaction  < public U FromAccount < get; set; >// денежный перевод со счета public U ToAccount < get; set; >// денежный перевод на счет public V Code < get; set; >// код транзакции public int Sum < get; set; >// сумма >

U и V — два универсальных параметра, используемые в классе Transaction .

Чтобы применить этот класс, необходимо объект Transaction типизировать с помощью string и :

Account acc1 = new Account < Sum = 4500 >; Account acc2 = new Account < Sum = 5000 >; Transaction transaction1 = new Transaction < FromAccount = acc1, ToAccount = acc2, Code = "45478758", Sum = 900 >;

Другими словами, вместо U теперь используется класс Account , а вместо параметра V — тип string .

Класс, типизируемый Transaction , является обобщенным.

Обобщенные методы

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

static void Swap (ref T a, ref T b)

Generic Methods или обобщенные методы меняют местами значения двух переменных:

int x = 5, y = 10; Swap (ref x, ref y);

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

Swap (ref x, ref y);

В обобщенном типе методы кастомно необобщенные. Чтобы сделать их таковыми, необходимо задать параметр типа. В данном примере это .

Пример кода Generics C#

/// /// Класс для демонстрации шаблонов. /// /// Тип данных. public class TemplateTest  < T[] arr = new T[10]; int index = 0; /// /// Добавление элемента в массив. /// /// Добавляемый элемент. /// Был ли добавлен элемент. public bool Add(T value) < if (index >= 10) < return false; >arr[index++] = value; return true; > /// /// Получить элемент по индексу. /// /// Индекс. /// Элемент по индексу. public T get(int index) < if (index < this.index && index >= 0) < return arr[index]; >else < return default(T); >> /// /// Получить количество элементов в массиве. /// /// Количество добавленных элементов. public int Count() < return index; >>

Шаблонный класс создан, и теперь у нас есть возможность использовать любой тип данных. Но поддержка всех типов данных не всегда нужна, потому при помощи ключевого слова where можно указать ограничения:

public class TemplateTest where T: YYYYY

где YYYYY может иметь значения:

  • класса;
  • struct ;
  • new() ;
  • имени класса;
  • имени интерфейса.

Класс Generics

Класс Generic определяется знаком после имени самого класса:

public class TestClass

В TestClass <> может быть использована любая буква.

Основные типы классов

Класс Generic Описание
Collection

Базис для generic-коллекции Compare. Сравнение двух объектов на равенство.
List

Список элементов с динамически изменяемым размером.
Stack

Реализация списка по принципу LIFO (last in, first out).
Queue

Реализация списка по принципу FIFO (first in, first out).
Dictionary

Generic-коллекция пар имя/значение.

Наследование класса Generics

Если базовый класс — это класс, который наследуется, то класс, который наследует, называется производным.

То есть производный класс — это особый вариант базового класса, который наследует все методы, свойства и переменные.

Разрешается вводить дополнительный класс в объявление другого класса. Это и называется наследованием.

Generics Interface

Чтобы создать Generics Interface, нужно, прежде всего, следовать правилам создания интерфейса:

public interface ICounter

Также нужно добавить элементы, которые необходимо переопределить. Рассмотрим пример получения generic-интерфейса из другого generic-интерфейса:

public interface ICounter  < int Count < get; >T Get(int index); >

Использование Generic с Exception

Определение Exception с параметрами Generics :

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GenericsTutorial < class MyException: ApplicationException < >>

Действительный Generic Exception :

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GenericsTutorial < class UsingGenericExceptionValid02 < public void SomeMethod() < try < // . >// Действительно catch (MyException e) < // Сделать что-то здесь. >// Действительно catch (MyException e) < // Сделать что-то здесь. >catch (Exception e) < >> > >

Метод Generics

Метод в классе может стать обобщенным.

Использование метода в Generics :

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GenericsTutorial < public class MyUtilsDemo < public static void Main(string[] args) < // K = int: Phone // V = string: Name KeyValueentry1 = new KeyValue(12000111, "Tom"); KeyValue entry2 = new KeyValue(12000112, "Jerry"); // (K = int). int phone = MyUtils.GetKey(entry1); Console.WriteLine("Phone = " + phone); // Списко содержит элементы вида KeyValue. List list = new List(); // Добавить элемент в список. list.Add(entry1); list.Add(entry2); KeyValue firstEntry = MyUtils.GetFirstElement(list, null); if (firstEntry != null) < Console.WriteLine("Value font-weight: 400;">Результат: 

Phone = 12000111. Value = Tom

Инициализация объекта Generic

public void DoSomething() < // Инициализировать объект Generic T t = new T(); // Error >

Обычно ошибкой инициализации объекта Generic является отсутствие T() в параметре Т . В таком случае следует добавить when T : new()

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GenericsTutorial < class GenericInitializationExample < // Вид T должен быть видом, имеющим Constructor по умолчанию. public void DoSomeThing() where T : new() < T t = new T(); >// Вид T должен быть видом, имеющим Constructor по умолчанию. // и расширенным из класса KeyValue. public void ToDoSomeThing() where K: KeyValue, new( ) < K key = new K(); >public T DoDefault() < // Возвращает null если T является ссылочным видом (reference type). // Или 0 если T является видом числа (int, float. ) return default(T); >> >

Массив Generic

C# позволяет объявлять обобщенные массивы:

T[] myArray = newT[10];

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GenericsTutorial < class GenericArrayExample < public static T[] FilledArray(T value, int count) < T[] ret = new T[count]; for (int i = 0; i < count; i++) < ret[i] = value; >return ret; > public static void Main(string[] args) < string value = "Hello"; string[] filledArray = FilledArray(value, 10); foreach (string s in filledArray) < Console.WriteLine(s); >> > >

Итоги

Обобщения позволяют указывать обрабатываемые данные в виде параметров (в методах, классах, структурах, интерфейсах).

Например, с помощью дженериков можно создать общий класс для обработки самых разных данных.

Основные преимущества обобщений:

  1. Безопасность. Исключают необходимость проверки соответствия типов в коде вручную.
  2. Повторное использование кода. Обобщенный класс определяется один раз, а дальше создаются копии.
  3. Производительность. Достигается з а счет отсутствия упаковки и распаковки значимых типов.

Видео: обобщения в C#

C# Generic & Non-generic Collections

C# includes specialized classes that store series of values or objects are called collections.

There are two types of collections available in C#: non-generic collections and generic collections.

The System.Collections namespace contains the non-generic collection types and System.Collections.Generic namespace includes generic collection types.

In most cases, it is recommended to use the generic collections because they perform faster than non-generic collections and also minimize exceptions by giving compile-time errors.

Generic Collections

C# includes the following generic collection classes in the System.Collections.Generic namespace.

Generic Collections Description
List Generic List contains elements of specified type. It grows automatically as you add elements in it.
Dictionary Dictionary contains key-value pairs.
SortedList SortedList stores key and value pairs. It automatically adds the elements in ascending order of key by default.
Queue Queue stores the values in FIFO style (First In First Out). It keeps the order in which the values were added. It provides an Enqueue() method to add values and a Dequeue() method to retrieve values from the collection.
Stack Stack stores the values as LIFO (Last In First Out). It provides a Push() method to add a value and Pop() & Peek() methods to retrieve values.
Hashset

Hashset contains non-duplicate elements. It eliminates duplicate elements.

Non-generic Collections

Non-generic Collections Usage
ArrayList ArrayList stores objects of any type like an array. However, there is no need to specify the size of the ArrayList like with an array as it grows automatically.
SortedList SortedList stores key and value pairs. It automatically arranges elements in ascending order of key by default. C# includes both, generic and non-generic SortedList collection.
Stack Stack stores the values in LIFO style (Last In First Out). It provides a Push() method to add a value and Pop() & Peek() methods to retrieve values. C# includes both, generic and non-generic Stack.
Queue Queue stores the values in FIFO style (First In First Out). It keeps the order in which the values were added. It provides an Enqueue() method to add values and a Dequeue() method to retrieve values from the collection. C# includes generic and non-generic Queue.
Hashtable Hashtable stores key and value pairs. It retrieves the values by comparing the hash value of the keys.
BitArray BitArray manages a compact array of bit values, which are represented as Booleans, where true indicates that the bit is on (1) and false indicates the bit is off (0).

Let's see each type of collection next.

Коллекции

Хотя в языке C# есть массивы, которые хранят в себе наборы однотипных объектов, но работать с ними не всегда удобно. Например, массив хранит фиксированное количество объектов, однако что если мы заранее не знаем, сколько нам потребуется объектов. И в этом случае намного удобнее применять коллекции. Еще один плюс коллекций состоит в том, что некоторые из них реализует стандартные структуры данных, например, стек, очередь, словарь, которые могут пригодиться для решения различных специальных задач. Большая часть классов коллекций содержится в пространстве имен System.Collections.Generic .

Класс List из пространства имен System.Collections.Generic представляет простейший список однотипных объектов. Класс List типизируется типом, объекты которого будут хранится в списке.

Мы можем создать пустой список:

List people = new List();

В данном случае объект List типизируется типом string . А это значит, что хранить в этом списке мы можем только строки.

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

List people = new List() < "Tom", "Bob", "Sam" >;

В данном случае в список помещаются три строки

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

var people = new List() < "Tom", "Bob", "Sam" >; var employees = new List(people);

Можно совместить оба способа:

var people = new List() < "Tom", "Bob", "Sam" >; var employees = new List(people);

В данном случае в списке employees будет четыре элемента ( < "Tom", "Bob", "Sam", "Mike" >) - три добавляются из списка people и один элемент задается при инициализации.

Подобным образом можно работать со списками других типов, например:

List people = new List() < new Person("Tom"), new Person("Bob"), new Person("Sam") >; class Person < public string Name < get;>public Person(string name) => Name = name; >

Установка начальной емкости списка

Еще один конструктор класса List принимает в качестве параметра начальную емкость списка:

List people = new List(16);

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

Также начальную емкость можно установить с помощью свойства Capacity , которое имеется у класса List.

Обращение к элементам списка

Как и массивы, списки поддерживают индексы, с помощью которых можно обратиться к определенным элементам:

var people = new List() < "Tom", "Bob", "Sam" >; string firstPerson = people[0]; // получаем первый элемент Console.WriteLine(firstPerson); // Tom people[0] = "Mike"; // изменяем первый элемент Console.WriteLine(people[0]); // Mike

Длина списка

С помощью свойства Count можно получить длину списка:

var people = new List() < "Tom", "Bob", "Sam" >; Console.WriteLine(people.Count); // 3

Перебор списка

C# позволяет осуществить перебор списка с помощью стандартного цикла foreach :/p>

var people = new List() < "Tom", "Bob", "Sam" >; foreach (var person in people) < Console.WriteLine(person); >// Вывод программы: // Tom // Bob // Sam

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

var people = new List() < "Tom", "Bob", "Sam" >; for (int i = 0; i

Методы списка

Среди его методов можно выделить следующие:

  • void Add(T item) : добавление нового элемента в список
  • void AddRange(IEnumerable collection) : добавление в список коллекции или массива
  • int BinarySearch(T item) : бинарный поиск элемента в списке. Если элемент найден, то метод возвращает индекс этого элемента в коллекции. При этом список должен быть отсортирован.
  • void CopyTo(T[] array) : копирует список в массив array
  • void CopyTo(int index, T[] array, int arrayIndex, int count) : копирует из списка начиная с индекса index элементы, количество которых равно count, и вставляет их в массив array начиная с индекса arrayIndex
  • bool Contains(T item) : возвращает true , если элемент item есть в списке
  • void Clear() : удаляет из списка все элементы
  • bool Exists(Predicate match) : возвращает true , если в списке есть элемент, который соответствует делегату match
  • T? Find(Predicate match) : возвращает первый элемент, который соответствует делегату match. Если элемент не найден, возвращается null
  • T? FindLast(Predicate match) : возвращает последний элемент, который соответствует делегату match. Если элемент не найден, возвращается null
  • List FindAll(Predicate match) : возвращает список элементов, которые соответствуют делегату match
  • int IndexOf(T item) : возвращает индекс первого вхождения элемента в списке
  • int LastIndexOf(T item) : возвращает индекс последнего вхождения элемента в списке
  • List GetRange(int index, int count) : возвращает список элементов, количество которых равно count, начиная с индекса index.
  • void Insert(int index, T item) : вставляет элемент item в список по индексу index. Если такого индекса в списке нет, то генерируется исключение
  • void InsertRange(int index, collection) : вставляет коллекцию элементов collection в текущий список начиная с индекса index. Если такого индекса в списке нет, то генерируется исключение
  • bool Remove(T item) : удаляет элемент item из списка, и если удаление прошло успешно, то возвращает true. Если в списке несколько одинаковых элементов, то удаляется только первый из них
  • void RemoveAt(int index) : удаление элемента по указанному индексу index. Если такого индекса в списке нет, то генерируется исключение
  • void RemoveRange(int index, int count) : параметр index задает индекс, с которого надо удалить элементы, а параметр count задает количество удаляемых элементов.
  • int RemoveAll((Predicate match)) : удаляет все элементы, которые соответствуют делегату match. Возвращает количество удаленных элементов
  • void Reverse() : изменяет порядок элементов
  • void Reverse(int index, int count) : изменяет порядок на обратный для элементов, количество которых равно count, начиная с индекса index
  • void Sort() : сортировка списка
  • void Sort(IComparer? comparer) : сортировка списка с помощью объекта comparer, который передается в качестве параметра

Добавление в список

List people = new List () < "Tom" >; people.Add("Bob"); // добавление элемента // people = < "Tom", "Bob" >; people.AddRange(new[] < "Sam", "Alice" >); // добавляем массив // people = < "Tom", "Bob", "Sam", "Alice" >; // также можно было бы добавить другой список // people.AddRange(new List()< "Sam", "Alice" >); people.Insert(0, "Eugene"); // вставляем на первое место // people = < "Eugene", "Tom", "Bob", "Sam", "Alice" >; people.InsertRange(1, new string[] ); // вставляем массив с индекса 1 // people = < "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam", "Alice" >; // также можно было бы добавить другой список // people.InsertRange(1, new List()< "Mike", "Kate" >);

Удаление из списка

var people = new List () < "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam", "Tom", "Alice" >; people.RemoveAt(1); // удаляем второй элемент // people = < "Eugene", "Kate", "Tom", "Bob", "Sam", "Tom", "Alice" >; people.Remove("Tom"); // удаляем элемент "Tom" // people = < "Eugene", "Kate", "Bob", "Sam", "Tom", "Alice" >; // удаляем из списка все элементы, длина строки которых равна 3 people.RemoveAll(person => person.Length == 3); // people = < "Eugene", "Kate", "Alice" >; // удаляем из списка 2 элемента начиная с индекса 1 people.RemoveRange(1, 2); // people = < "Eugene">; // полностью очищаем список people.Clear(); // people = < >;

Поиск и проверка элемента

var people = new List () < "Eugene", "Mike", "Kate", "Tom", "Bob", "Sam" >; var containsBob = people.Contains("Bob"); // true var containsBill = people.Contains("Bill"); // false // проверяем, есть ли в списке строки с длиной 3 символа var existsLength3 = people.Exists(p => p.Length == 3); // true // проверяем, есть ли в списке строки с длиной 7 символов var existsLength7 = people.Exists(p => p.Length == 7); // false // получаем первый элемент с длиной в 3 символа var firstWithLength3 = people.Find(p => p.Length == 3); // Tom // получаем последний элемент с длиной в 3 символа var lastWithLength3 = people.FindLast(p => p.Length == 3); // Sam // получаем все элементы с длиной в 3 символа в виде списка List peopleWithLength3 = people.FindAll(p => p.Length == 3); // peopleWithLength3

Получение диапазона и копирование в массив

List people = new List() ; // получаем диапазон со второго по четвертый элемент var range = people.GetRange(1, 3); // range = < "Tom", "Mike", "Sam">; // копируем в массив первые три элемента string[] partOfPeople = new string[3]; people.CopyTo(0, partOfPeople, 0, 3); // partOfPeople = < "Eugene", "Tom", "Mike">;

Расположение элементов в обратном порядке

var people = new List () < "Eugene", "Tom", "Mike", "Sam", "Bob" >; // переворачиваем весь список people.Reverse(); // people = < "Bob","Sam", "Mike", "Tom", "Eugene">; var people2 = new List() < "Eugene", "Tom", "Mike", "Sam", "Bob" >; // переворачиваем часть только 3 элемента с индекса 1 people2.Reverse(1, 3); // people2 = < "Eugene","Sam", "Mike", "Tom", "Bob" >;

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *