Enumerările sunt structuri care seamănă cu clasele, dar diferă de acestea prin faptul că în corpul enumerărilor putem declara doar constante. O varietate de constante conectate logic pot fi corelate la nivel sintactic. Aceste elemente de limbaj sunt așa-numitele tipuri enumerate.
La nivel de concept, enumerările pot fi declarate folosind cuvântul cheie C# enum, în loc de class:
|
1
2
3
4
|
[<modificatori_acces>] enum
<nume_enum>
{
constanta1 [, constanta2 [, [, ... [, constantaN]]]]
}
|
În șablonul de mai sus, modificatorul de acces poate fi public sau internal, atunci când declarăm enumerarea direct într-un namespace, și public, internal, internal protected sau private atunci când o declarăm într-o clasă. Identificatorul nume_enum trebuie să respecte regulile de denumire a claselor. În cele din urmă, constantele sunt declarate în interiorul corpului enumerării, separate prin virgulă.
Să luăm un exemplu de enumerare, zilele săptămânii:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
namespace
BunaLume
{
public enum
Zile
{
Luni,
Marti,
Miercuri,
Joi,
Vineri,
Sambata,
Duminica
}
}
|
Deci, puteți spune că ați declarat o enumerare de tip Zile, care conține 7 constante denumite cu numele zilelor săptămânii. Ceea ce nu știți este faptul că în fundal, C# atribuie valori de tip întreg constantelor enumerărilor. De aceea, codul de mai sus este similar cu acesta:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
namespace
BunaLume
{
public enum
Zile
{
Luni = 0,
Marti = 1,
Miercuri = 2,
Joi = 3,
Vineri = 4,
Sambata = 5,
Duminica = 6
}
}
|
și putem testa acest lucru prin convertirea unuia dintre membrii enum la un număr întreg:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
namespace
BunaLume
{
public enum
Zile
{
Luni,
Marti,
Miercuri,
Joi,
Vineri,
Sambata,
Duminica
}
class
Program
{
static void Main(string[] args)
{
int valoareLuni = (int)Zile.Luni;
Console.WriteLine(valoareLuni);
Console.ReadLine();
}
}
}
|
iar rezultatul va fi 0. Cu toate acestea, nu putem spune că Zile.Luni este de tip int, deoarece nu este, chiar dacă acesta deține o valoare întregă; este de tip Zile, după cum putem verifica:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
namespace
BunaLume
{
public enum
Zile
{
Luni,
Marti,
Miercuri,
Joi,
Vineri,
Sambata,
Duminica
}
class
Program
{
static void Main(string[] args)
{
Console.WriteLine(Zile.Luni este int);
Console.WriteLine(Zile.Luni este Zile);
Console.ReadLine();
}
}
}
|
Cuvântul cheie C# is este util pentru verificarea tipului unui membru, returnând o valoare booleană: true dacă membrul este de tipul pe care l-am verificat, sau false dacă nu este. Deci, testul nostru va afișa:
deoarece Zile.Luni nu este de tip int, dar este de tip Zile.
S-ar putea să vă întrebați de ce a trebuit să convertesc Zile.Luni în int, și nu i-am afișat valoarea astfel:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
namespace
BunaLume
{
public enum
Zile
{
Luni,
Marti,
Miercuri,
Joi,
Vineri,
Sambata,
Duminica
}
class
Program
{
static void Main(string[] args)
{
Console.WriteLine(Zile.Luni);
Console.ReadLine();
}
}
}
|
Ei bine, dacă rulați exemplul de mai sus, veți observa că rezultatul afișat nu va fi 0, ci Luni!
Deci, acum vă pot da definiția academică a enumerărilor: o enumerare este de fapt o reprezentare textuală a unui întreg. Implicit, acest număr este indicele constantei din lista constantelor unui anumit tip de enumerare.
Un lucru foarte util al enumerărilor este acela că putem atribui valori personalizate constantelor sale:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
namespace
BunaLume
{
public enum
Zile
{
Luni = 13,
Marti = 205,
Miercuri,
Joi,
Vineri,
Sambata,
Duminica
}
}
|
Prin urmare, am aflat ce sunt enumerările, ce putem face cu ele, etc, dar cum ne sunt ele de fapt folositoare? Să luăm în considerare un exemplu din viața reală. Avem un automat de cafea:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
namespace
BunaLume
{
public class
Program
{
static void Main(string[] args)
{
Cafea cafea = new Cafea();
Console.ReadLine();
}
}
public class
Cafea
{
public Cafea()
{
}
}
}
|
Minunat! Tocmai am comandat o cafea! Dar ce se întâmplă dacă vrem să specificăm dimensiunea cafelei? Desigur, putem folosi o proprietate, și o putem seta în constructor:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
namespace
BunaLume
{
public class
Program
{
static void Main(string[] args)
{
Cafea cafea = new Cafea(150);
Console.ReadLine();
}
}
public class
Cafea
{
private int marimeCafea = 100;
private int MarimeCafea
{
get { return marimeCafea; }
set { marimeCafea = value; }
}
public Cafea(int marimeCafea)
{
this.marimeCafea = marimeCafea;
}
}
}
|
Codul de mai sus funcționează perfect, cu o singură excepție: utilizatorii pot seta orice valoare doresc, să zicem, 1056 ml. Sigur, putem face câteva verificări if-else în interiorul proprietății, sigur, putem să generăm câteva excepții, dar aceasta nu este o soluție foarte elegantă, mai ales dacă există o mulțime de cazuri individuale. De asemenea, am putea să facem variabila marimeCafea o constantă, dar asta nu ne-ar ajuta cu nimic, deoarece nu am putea să specificăm cantitatea dorită.
Iată unde enumerările ne pot veni în ajutor. Să creăm o enumerare a cantităților disponibile:
|
1
2
3
4
5
6
|
public enum MarimeCafea
{
Expresso = 100,
Normala = 150,
Dubla = 300
}
|
Începeți să îi vedeți frumusețea? Deoarece am spus că enumerările conțin doar constante, valorile pe care le-am stabilit vor fi singurele valori disponibile pentru utilizatori și nu vor putea fi modificate. Este exact ceea ce aveam nevoie. Deci, cum folosim această enumerare în exemplul nostru? La începutul acestei lecții, am spus că enumerările seamănă cu clasele, cu diferența că pot conține numai câmpuri constante. Acest lucru înseamnă și că folosim enumerările în același mod în care folosim clasele: utilizând instanțierea sau câmpuri/proprietăți.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
namespace
BunaLume
{
public enum MarimeCafea
{
Expresso = 100,
Normala = 150,
Dubla = 300
}
public class
Cafea
{
private MarimeCafea marimeCafea;
public MarimeCafea MarimeCafea
{
get { return marimeCafea; }
}
public Cafea(MarimeCafea marimeCafea)
{
this.marimeCafea = marimeCafea;
}
}
}
|
Codul este destul de ușor de înțeles: am declarat o enumerare numită MarimeCafea, apoi în clasa noastră Cafea declarăm un câmp și o proprietate, ambele de tipul MarimeCafea. În final, am setat valoarea câmpului și în constructorul clasei. Deci, acum putem avea acest fel de comandă de cafea:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
namespace
BunaLume
{
public enum MarimeCafea
{
Expresso = 100,
Normala = 150,
Dubla = 300
}
public class
Cafea
{
private MarimeCafea marimeCafea;
public MarimeCafea MarimeCafea
{
get { return marimeCafea; }
}
public Cafea(MarimeCafea marimeCafea)
{
this.marimeCafea = marimeCafea;
}
}
public class
Program
{
static void Main(string[] args)
{
Cafea cafeaNormala = new Cafea(MarimeCafea.Normala);
Cafea cafeaDubla = new Cafea(MarimeCafea.Dubla);
Console.WriteLine("Cafeaua {0} are {1} ml.", cafeaNormala.MarimeCafea, (int)cafeaNormala.MarimeCafea);
Console.WriteLine("Cafeaua {0} are {1} ml.", cafeaDubla.MarimeCafea, (int)cafeaDubla.MarimeCafea);
Console.ReadLine();
}
}
}
|
Acesta este exact ceea ce doream în primul rând, abilitatea de a alege dintr-un set predefinit de valori constante. Și, da, nu putem schimba valorile membrilor enum, după ce le-am declarat:
pentru că am obține o eroare: Partea din stânga a unei alocări trebuie să fie o variabilă, proprietate sau indexer (The left-hand side of an assignment must be a variable, property or indexer).
Un ultim lucru pe care trebuie să îl știți despre enumerări este faptul că ele sunt tipuri de referință, dar valorile din interiorul lor sunt tipuri de valoare.