enum (от слова "enumeration", которое переводится как "перечисление") является особенным типом данных в C#, который позволяет создавать и управлять набором связанных констант.
enum является значимым (value) типом и наследует от класса System.Enum. Но важно помнить, что это наследование не тоже самое, что и обычное наследование в ООП. В смысле ООП, enum не поддерживает наследование и не может быть производным от любого другого класса или enum, кроме System.Enum.
enum обычно используется для создания набора констант, которые являются логически связанными. Например, дни недели, уровни сложности игры, состояния кнопки и т.д.
Если вы определите перечисления и не присвоите ей значение, она будет инициализирована значением default, которое для перечислений равно 0.
Перечисления определяются с помощью ключевого слова enum. Например:
```csharp
public enum Days
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
```
<br>
Каждому элементу в enum автоматически присваивается целочисленное значение, начиная с нуля, и увеличивается на единицу для каждого последующего элемента. Однако, вы можете явно установить значения для каждого элемента, если хотите. Например:
```csharp
public enum Days
{
Monday = 1,
Tuesday = 2,
// и так далее...
}
```
<br>
Чтобы использовать enum, вы просто создаёте переменную типа enum и присваиваете ей значение из enum. Например:
```csharp
Days day = Days.Monday;
```
<br>
**Типы:** По умолчанию, enum имеет базовый тип int. Вы можете изменить базовый тип на любой другой целочисленный тип (byte, sbyte, short, ushort, int, uint, long, ulong). Например:
```csharp
public enum Days : byte
{
Monday,
Tuesday,
// и так далее...
}
```
<br>
**Преобразования типов**: Вы можете преобразовать значение enum в его числовое значение и наоборот с помощью приведения типов. Например:
```csharp
Days day = Days.Monday;
int dayNumber = (int)day; // dayNumber будет равно 0 (или 1, если Monday = 1)
```
<br>
В обратную сторону:
```csharp
int dayNumber = 1;
Days day = (Days)dayNumber; // day будет равно Days.Monday
```
<br>
**Flags Attribute**: Если вам нужно представить набор значений, которые можно комбинировать (как битовые флаги), вы можете использовать атрибут [Flags]. Это позволяет объединять значения enum с помощью операций OR, AND и XOR. Например:
```csharp
[Flags]
public enum FileAccess
{
None = 0,
Read = 1,
Write = 2,
ReadWrite = Read | Write // это объединение Read и Write
}
```
### Методы
**Enum.ToString()**: Метод ToString() может быть использован для преобразования значения enum в строку.
```csharp
Days day = Days.Monday;
Console.WriteLine(day.ToString()); // выведет "Monday"
```
<br>
**Enum.Parse() и Enum.TryParse()**: Методы Parse() и TryParse() используются для преобразования строки в значение enum.
```csharp
string dayString = "Monday";
Days day = (Days) Enum.Parse(typeof(Days), dayString);
```
<br>
**Enum.IsDefined()**: Метод IsDefined() можно использовать, чтобы проверить, существует ли определенное значение в enum.
```csharp
bool isDefined = Enum.IsDefined(typeof(Days), "Monday"); // вернет true
```
<br>
**Enum.GetValues() и Enum.GetNames()**: Методы GetValues() и GetNames() используются для получения массива всех значений или имен в enum.
```csharp
Array values = Enum.GetValues(typeof(Days));
string[] names = Enum.GetNames(typeof(Days));
```
Метод Enum.GetValues() возвращает массив значений перечисления в виде экземпляра System.Array, но тип элементов массива будет соответствовать типу базового перечисления. По умолчанию это int, если вы не определите иначе, но перечисления могут иметь другие базовые типы, такие как byte, sbyte, short, ushort, int, uint, long или ulong.
Поскольку массивы в C# должны содержать элементы одного типа, и тип перечисления в этом контексте не известен до времени выполнения, то System.Array используется как общий тип для всех возможных типов перечислений.
<br>
**Enum.Format(Type, Object, String)**: Преобразует значение указанного перечисления в эквивалентное строковое представление в соответствии с указанным форматом.
**Enum.HasFlag(Enum)**: Определяет, установлен ли один или несколько битовых флагов в текущем экземпляре. Этот метод полезен, когда enum используется с атрибутом Flags.
**Enum.CompareTo(Object)**: Сравнивает этот экземпляр с заданным объектом и возвращает указание их относительных значений.
Обратите внимание, что методы Enum.HasFlag(), Enum.CompareTo() и Enum.ToString() являются методами экземпляра, вызываемыми непосредственно на значении перечисления, а не статическими методами Enum.
### Вопросы
##### Можно ли сделать так, чтобы в c# метод принимал любой enum? допустим, у меня есть два вида enum
Да, в C# вы можете создать метод, который принимает любой тип enum с использованием обобщений (generics) и ограничений типа (type constraints).
Вот пример метода, который принимает любой enum:
```csharp
using System;
public static class EnumExtensions
{
public static void ProcessEnum<TEnum>(TEnum enumValue) where TEnum : Enum
{
// Обработка значения enum здесь
Console.WriteLine(
quot;Enum value: {enumValue}");
}
}
```
Здесь мы создаем статический класс EnumExtensions, который содержит метод ProcessEnum. Этот метод использует обобщение TEnum, которое ограничено типом Enum. В результате, метод будет работать только с типами, производными от Enum.
Теперь вы можете вызвать этот метод с любым enum:
```csharp
public enum EnumType1
{
Value1,
Value2
}
public enum EnumType2
{
ValueA,
ValueB
}
public static void Main(string[] args)
{
EnumExtensions.ProcessEnum(EnumType1.Value1);
EnumExtensions.ProcessEnum(EnumType2.ValueA);
}
```
Это позволит использовать метод ProcessEnum с любыми типами enum, такими как EnumType1 и EnumType2.
##### А можно ли сделать так, чтобы метод принимал только определенные виды enum’ов?
Да, вы можете создать метод, который принимает только определенные типы enum, используя перегрузку методов. В этом случае, вам нужно создать отдельную перегрузку для каждого enum, который вы хотите принимать.
Вот пример с двумя перегруженными методами, каждый из которых принимает определенный enum:
```csharp
public enum EnumType1
{
Value1,
Value2
}
public enum EnumType2
{
ValueA,
ValueB
}
public static class EnumProcessor
{
public static void ProcessEnum(EnumType1 enumValue)
{
// Обработка значения EnumType1 здесь
Console.WriteLine(quot;EnumType1 value: {enumValue}");
}
public static void ProcessEnum(EnumType2 enumValue)
{
// Обработка значения EnumType2 здесь
Console.WriteLine(quot;EnumType2 value: {enumValue}");
}
}
public static void Main(string[] args)
{
EnumProcessor.ProcessEnum(EnumType1.Value1);
EnumProcessor.ProcessEnum(EnumType2.ValueA);
}
```
В этом примере создается статический класс EnumProcessor с двумя перегруженными методами ProcessEnum. Один из них принимает EnumType1, а другой - EnumType2. Вы можете вызвать соответствующую перегрузку, передав нужный enum.
Это ограничивает использование метода ProcessEnum только двумя определенными типами enum. Если вы хотите добавить поддержку другого enum, вам потребуется создать еще одну перегрузку метода.