Руководство C# Generics
1. Класс Generics
Пример ниже дает определение классу generics. KeyValue это класс generics, который содержит пару ключей и значение (key/value).
KeyValue.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
public class KeyValue<K, V>
{
private K key;
private V value;
public KeyValue(K key, V value)
{
this.key = key;
this.value = value;
}
public K GetKey()
{
return key;
}
public void SetKey(K key)
{
this.key = key;
}
public V GetValue()
{
return value;
}
public void SetValue(V value)
{
this.value = value;
}
}
}
K, V в классе KeyValue<K,V> называются параметрами generics, это определенный вид данных. При использовании этого класса, вам нужно опредеилть конкретный параметр.
Посмотрим пример использования класса KeyValue.
KeyValueDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
public class KeyValueDemo
{
public static void Main(string[] args)
{
// Создать объект KeyValue.
// int: Номер телефона (K = int)
// string: Имя пользователя. (V = string).
KeyValue<int, string> entry = new KeyValue<int, string>(12000111, "Tom");
// C# понимает возвращенный вид как int (K = int).
int phone = entry.GetKey();
// C# понимает возвращенный вид как string (V = string).
string name = entry.GetValue();
Console.WriteLine("Phone = " + phone + " / name = " + name);
Console.Read();
}
}
}
Запуск примера:
Phone = 12000111 / name = Tom
2. Наследование класса Generics
Расширенный класс из класса generics, который может определить вид параметра для generics, оставить параметры generics или добавить параметры generics.
Пример 1:
PhoneNameEntry.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
// Данный класс расширен из класса KeyValue<K,V>
// И ясно определяет вид для 2 параметров K & V
// K = int (Номер телефона).
// V = string (Имя пользователя).
public class PhoneNameEntry : KeyValue<int, string>
{
public PhoneNameEntry(int key, string value)
: base(key, value)
{
}
}
}
Пример использования PhoneNameEntry:
PhoneNameEntryDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
public class PhoneNameEntryDemo
{
public static void Main(string[] args)
{
PhoneNameEntry entry = new PhoneNameEntry(12000111, "Tom");
// C# понимает возвращенный вид как int.
int phone = entry.GetKey();
// C# понимает возвращенный вид как string.
string name = entry.GetValue();
Console.WriteLine("Phone = " + phone + " / name = " + name);
Console.Read();
}
}
}
Example 2:
StringAndValueEntry.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
// Данный класс расширен из класса KeyValue<K,V>
// Ясно определить параметр K как String.
// Оставить вид параметра generic V.
public class StringAndValueEntry<V> : KeyValue<string, V>
{
public StringAndValueEntry(string key, V value)
: base(key, value)
{
}
}
}
Пример использования класса StringAndValueEntry:
StringAndValueEntryDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
public class StringAndValueEntryDemo
{
public static void main(String[] args)
{
// (Код сотрудника, Имя сотрудника).
// V = string (Имя сотрудника)
StringAndValueEntry<String> entry = new StringAndValueEntry<String>("E001", "Tom");
String empNumber = entry.GetKey();
String empName = entry.GetValue();
Console.WriteLine("Emp Number = " + empNumber);
Console.WriteLine("Emp Name = " + empName);
Console.Read();
}
}
}
Пример 3:
KeyValueInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
// Данный класс расширен из класса KeyValue<K,V>.
// Он имеет еще один параметр Generics I.
public class KeyValueInfo<K, V, I> : KeyValue<K, V>
{
private I info;
public KeyValueInfo(K key, V value)
: base(key, value)
{
}
public KeyValueInfo(K key, V value, I info)
: base(key, value)
{
this.info = info;
}
public I GetInfo()
{
return info;
}
public void GetInfo(I info)
{
this.info = info;
}
}
}
3. Generics Interface
Interface с параметром Generics:
GenericInterface.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
public interface GenericInterface<G>
{
G DoSomething();
}
}
Например, класс выполняет (implements) Interface:
GenericInterfaceImpl.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
public class GenericInterfaceImpl<G> : GenericInterface<G>
{
private G something;
public G DoSomething()
{
return something;
}
}
}
4. Использование Generic с Exception
Вы можете определить Exception с параметрами Generics.
MyException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
class MyException<E> : ApplicationException
{
}
}
Использование действительного Generic Exception:
UsingGenericExceptionValid01.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
class UsingGenericExceptionValid01
{
public void SomeMethod()
{
try
{
// ...
}
// Действительно
catch (MyException<string> e)
{
// Сделать что-то здесь.
}
// Действительно
catch (MyException<int> e)
{
// Сделать что-то здесь.
}
catch (Exception e)
{
}
}
}
}
Использование действительного Generic Exception:
UsingGenericExceptionValid02.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
class UsingGenericExceptionValid02<K>
{
public void SomeMethod()
{
try
{
// ...
}
// Действительно
catch (MyException<string> e)
{
// Сделать что-то здесь.
}
// Действительно
catch (MyException<K> e)
{
// Сделать что-то здесь.
}
catch (Exception e)
{
}
}
}
}
Использование недействительного Generic Exception:
UsingGenericExceptionInvalid.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
class UsingGenericExceptionInvalid
{
public void SomeMethod()
{
try
{
// ...
}
// Действительно
//
catch (MyException<string> e)
{
// Сделать что-то здесь.
}
// Invalid (Unknown parameter K) ***********
// catch (MyException<K> e)
// {
// ...
// }
catch (Exception e)
{
}
}
}
}
5. Метод generics
Метод в класс или интерфейсе может быть стать Generic (generify).
MyUtils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GenericsTutorial
{
public class MyUtils
{
// <K,V> : Говорит этот метод имеет 2 вида параметра K,V
// Метод возвращает вид K.
public static K GetKey<K, V>(KeyValue<K, V> entry)
{
K key = entry.GetKey();
return key;
}
// <K,V> : Говорит этот метод имеет 2 вида параметра K,V
// Метод возвращает вид V.
public static V GetValue<K, V>(KeyValue<K, V> entry)
{
V value = entry.GetValue();
return value;
}
// List<E>: Список содержит элементы вида E
// Данный метод возвращает вид E.
public static E GetFirstElement<E>(List<E> list, E defaultValue)
{
if (list == null || list.Count == 0)
{
return defaultValue;
}
E first = list.ElementAt(0);
return first;
}
}
}
Пример использования метода generics:
MyUtilsDemo.cs
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
KeyValue<int, string> entry1 = new KeyValue<int, String>(12000111, "Tom");
KeyValue<int, string> entry2 = new KeyValue<int, String>(12000112, "Jerry");
// (K = int).
int phone = MyUtils.GetKey(entry1);
Console.WriteLine("Phone = " + phone);
// Списко содержит элементы вида KeyValue<int,string>.
List<KeyValue<int, string>> list = new List<KeyValue<int, string>>();
// Добавить элемент в список.
list.Add(entry1);
list.Add(entry2);
KeyValue<int, string> firstEntry = MyUtils.GetFirstElement(list, null);
if (firstEntry != null)
{
Console.WriteLine("Value = " + firstEntry.GetValue());
}
Console.Read();
}
}
}
Запуск примера:
Phone = 12000111
Value = Tom
6. Инициализация объекта Generic
Иногда вы хотите инициализировать объект Generic:
public void DoSomething<T>()
{
// Инициализировать объект Generic
T t = new T(); // Error
}
Причина ошибки выше, является то, что параметр Т возможно не имеет конструктор (constructor) T(), поэтому ам нужно добавить принуждение when T : new(). Посмотрим пример ниже:
GenericInitializationExample.cs
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<T>()
where T : new()
{
T t = new T();
}
// Вид T должен быть видом, имеющим Constructor по умолчанию.
// и расширенным из класса KeyValue.
public void ToDoSomeThing<K>()
where K: KeyValue<K,string>, new( )
{
K key = new K();
}
public T DoDefault<T>()
{
// Возвращает null если T является ссылочным видом (reference type).
// Или 0 если T является видом числа (int, float,..)
return default(T);
}
}
}
7. Массив Generic
В C# вы можете объявить массив Generics:
// Инициализировать массив.
T[] myArray = new T[10];
GenericArrayExample.cs
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>(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<string>(value, 10);
foreach (string s in filledArray)
{
Console.WriteLine(s);
}
}
}
}
Pуководства C#
- Наследование и полиморфизм в C#
- Что мне нужно для начала работы с C#?
- Быстрый обучение C# для начинающих
- Установите Visual Studio 2013 в Windows
- Абстрактный класс и Interface в C#
- Установите Visual Studio 2015 в Windows
- Сжатие и декомпрессия в C#
- Руководство по программированию многопоточности C#
- Руководство C# Delegate и Event
- Установите AnkhSVN в Windows
- Программирование C# для группы использующей Visual Studio и SVN
- Установить .Net Framework
- Access Modifier (Модификатор доступа) в C#
- Руководство C# String и StringBuilder
- Руководство C# Property
- Руководство C# Enum
- Руководство C# Structure
- Руководство C# Generics
- Обработка исключений для C#
- Руководство C# Date Time
- Манипулирование файлами и каталогами в C#
- Руководство CSharp Streams - двоичные потоки в C#
- Руководство Регулярное выражение C#
- Подключиться к базе данных SQL Server в C#
- Работа с базой данных SQL Server на C#
- Подключиться к базе данных MySQL в C#
- Работа с базой данных MySQL на C#
- Подключиться к базе данных Oracle в C# без Oracle Client
- Работа с базой данных Oracle на C#
Show More