Вот более объектно-ориентированный способ, возможно, достичь того, чего вы пытаетесь достичь. Это решение основано на раннем Java-подходе к перечислению:
struct Sport {
readonly int value;
public Sport(int value) {
this.value = value;
}
public static implicit operator int(Sport sport) {
return sport.value;
}
public static implicit operator Sport(int sport) {
return new Sport(sport);
}
public const int Tennis = 0;
public const int Football = 1;
public const int Squash = 2;
public const int Volleyball = 3;
}
//Usage:
Sport sport = Sport.Volleyball;
switch(sport) {
case Sport.Squash:
Console.WriteLine("I bounce really high");
break;
}
Sport rugby = 5;
if (sport == rugby)
Console.WriteLine("I am really big and eat a lot");
Чтобы пройти через различные возможности этого решения.
Это неизменяемая структура, которая заключает в себе целочисленное значение. Значение принудительно устанавливается неизменным по ключевому слову readonly
.
Единственный способ создать одну из этих структур - вызвать конструктор, который принимает значение в качестве параметра.
implicit operator int
существует для того, чтобы структуру можно было использовать в блоке switch
- то есть, чтобы сделать структуру конвертируемой в int
.
implicit operator Sport
существует для того, чтобы вы могли присваивать целочисленные значения структуре, т.е. Sport rugby = 5
.
const
- это виды спорта, известные во время компиляции. Их также можно использовать как метки case
.
Что бы я на самом деле делал
public static class Sports {
public static readonly Sport Football = new Sport("Football");
public static readonly Sport Tennis = new Sport("Tennis");
}
public class Sport {
public Sport(string name) {
Name = name;
}
public string Name { get; private set; }
// override object.Equals
public override bool Equals(object obj) {
var other = obj as Sport;
if(other == null) {
return false;
}
return other == this;
}
// override object.GetHashCode
public override int GetHashCode() {
return Name.GetHashCode();
}
public static bool operator == (Sport sport1, Sport sport2) {
if(Object.ReferenceEquals(sport1, null) && Object.ReferenceEquals(sport2 , null))
return true;
if(Object.ReferenceEquals(sport1, null) || Object.ReferenceEquals(sport2, null))
return false;
return sport1.Name == sport2.Name;
}
public static bool operator !=(Sport sport1, Sport sport2) {
return !(sport1 == sport2);
}
}
Это создаст класс значений Sport
с именем. В зависимости от вашего приложения вы можете расширить этот класс для предоставления других атрибутов и методов. Наличие этого класса дает вам больше гибкости, так как вы можете создавать его подклассы.
Sports
класс предоставляет статическую коллекцию видов спорта, которые известны во время компиляции. Это похоже на то, как некоторые платформы .NET обрабатывают именованные цвета (например, WPF). Вот использование:
List<Sport> sports = new List<Sport>();
sports.Add(Sports.Football);
sports.Add(Sports.Tennis);
//What if the name contains spaces?
sports.Add(new Sport("Water Polo"));
var otherSport = new Sport("Other sport");
if(sports.Contains(otherSport)) {
//Do something
}
foreach(var sport in sports) {
if(sport == otherSport) {
//Do Something
} else if(sport == Sports.Football) {
//do something else
}
}
Как только вы это сделаете, вы обнаружите, что фактически нет нужды в перечислении, так как любые условные операции для спортивного типа могут выполняться в классе Sport
.
EDIT Понял, что мой оператор равенства выдает StackOverflowException
Я всегда забываю написать Object.ReferenceEquals(obj,null)
вместо obj==null
, что будет повторяться бесконечно.