Выбор значения по умолчанию для типа Enum без необходимости изменения значений
В C# возможно ли украсить тип Enum атрибутом или сделать что-то еще, чтобы указать, каким должно быть значение по умолчанию, без изменения значений? Требуемые числа могут быть установлены в камне по любой причине, и было бы удобно по-прежнему контролировать по умолчанию.
enum Orientation
{
None = -1,
North = 0,
East = 1,
South = 2,
West = 3
}
Orientation o; // Is 'North' by default.
14 ответов
По умолчанию для enum
(фактически любой тип значения) равен 0 - даже если это недопустимое значение для этого enum
, Это не может быть изменено.
Значение по умолчанию любого перечисления равно нулю. Поэтому, если вы хотите установить один перечислитель в качестве значения по умолчанию, то установите для него значение нуля, а для всех остальных перечислителей - ненулевое значение (первый перечислитель со значением ноль будет значением по умолчанию для этого перечисления, если существует несколько перечислителей). со значением ноль).
enum Orientation
{
None = 0, //default value since it has the value '0'
North = 1,
East = 2,
South = 3,
West = 4
}
Orientation o; // initialized to 'None'
Если вашим перечислителям не нужны явные значения, просто убедитесь, что первым перечислителем является тот, который вы хотите использовать в качестве перечислителя по умолчанию, поскольку "по умолчанию первый перечислитель имеет значение 0, а значение каждого последующего перечислителя увеличивается на 1." ( C# ссылка)
enum Orientation
{
None, //default value since it is the first enumerator
North,
East,
South,
West
}
Orientation o; // initialized to 'None'
Если ноль не работает как правильное значение по умолчанию, вы можете использовать модель компонента, чтобы определить обходной путь для перечисления:
[DefaultValue(None)]
public enum Orientation
{
None = -1,
North = 0,
East = 1,
South = 2,
West = 3
}
public static class Utilities
{
public static TEnum GetDefaultValue<TEnum>() where TEnum : struct
{
Type t = typeof(TEnum);
DefaultValueAttribute[] attributes = (DefaultValueAttribute[])t.GetCustomAttributes(typeof(DefaultValueAttribute), false);
if (attributes != null &&
attributes.Length > 0)
{
return (TEnum)attributes[0].Value;
}
else
{
return default(TEnum);
}
}
}
и тогда вы можете позвонить:
Orientation o = Utilities.GetDefaultValue<Orientation>();
System.Diagnostics.Debug.Print(o.ToString());
Примечание: вам нужно будет включить следующую строку в верхней части файла:
using System.ComponentModel;
Это не изменяет фактическое значение по умолчанию для языка C# перечисления, но дает возможность указать (и получить) желаемое значение по умолчанию.
По умолчанию для перечисления используется любое перечисление, равное нулю. Я не верю, что это можно изменить с помощью атрибутов или других средств.
(MSDN говорит: "Значение по умолчанию для перечисления E - это значение, полученное выражением (E)0.")
Еще один способ, который может быть полезен - использовать какой-то "псевдоним". Например:
public enum Status
{
New = 10,
Old = 20,
Actual = 30,
// Use Status.Default to specify default status in your code.
Default = New
}
Вы не можете, но если хотите, можете сделать какой-то трюк.:)
public struct Orientation
{
...
public static Orientation None = -1;
public static Orientation North = 0;
public static Orientation East = 1;
public static Orientation South = 2;
public static Orientation West = 3;
}
использование этой структуры как простого перечисления.
где вы можете создать pa == Orientation.East (или любое другое значение по умолчанию)
чтобы использовать сам трюк, вам нужно конвертировать из int по коду.
есть реализация:
#region ConvertingToEnum
private int val;
static Dictionary<int, string> dict = null;
public Orientation(int val)
{
this.val = val;
}
public static implicit operator Orientation(int value)
{
return new Orientation(value - 1);
}
public static bool operator ==(Orientation a, Orientation b)
{
return a.val == b.val;
}
public static bool operator !=(Orientation a, Orientation b)
{
return a.val != b.val;
}
public override string ToString()
{
if (dict == null)
InitializeDict();
if (dict.ContainsKey(val))
return dict[val];
return val.ToString();
}
private void InitializeDict()
{
dict = new Dictionary<int, string>();
foreach (var fields in GetType().GetFields(BindingFlags.Public | BindingFlags.Static))
{
dict.Add(((Orientation)fields.GetValue(null)).val, fields.Name);
}
}
#endregion
На самом деле enum
по умолчанию это первый элемент в enum
чья ценность 0
,
Так, например:
public enum Animals
{
Cat,
Dog,
Pony = 0,
}
//its value will actually be Cat not Pony unless you assign a non zero value to Cat.
Animals animal;
The default value of enum is the enummember equal to 0 or the first element(if value is not specified)
... Но я столкнулся с критическими проблемами, используя enum в своих проектах, и преодолел их, выполнив что-то ниже... Как бы то ни было, моя потребность была связана с уровнем класса...
class CDDtype
{
public int Id { get; set; }
public DDType DDType { get; set; }
public CDDtype()
{
DDType = DDType.None;
}
}
[DefaultValue(None)]
public enum DDType
{
None = -1,
ON = 0,
FC = 1,
NC = 2,
CC = 3
}
и получить ожидаемый результат
CDDtype d1= new CDDtype();
CDDtype d2 = new CDDtype { Id = 50 };
Console.Write(d1.DDType);//None
Console.Write(d2.DDType);//None
А что если значение поступает из БД.... Хорошо, в этом сценарии... передайте значение в функцию ниже, и она преобразует значение в перечисление... функция ниже обрабатывает различные сценарии, и это универсально... и поверьте мне, это так очень быстро.....:)
public static T ToEnum<T>(this object value)
{
//Checking value is null or DBNull
if (!value.IsNull())
{
return (T)Enum.Parse(typeof(T), value.ToStringX());
}
//Returanable object
object ValueToReturn = null;
//First checking whether any 'DefaultValueAttribute' is present or not
var DefaultAtt = (from a in typeof(T).CustomAttributes
where a.AttributeType == typeof(DefaultValueAttribute)
select a).FirstOrNull();
//If DefaultAttributeValue is present
if ((!DefaultAtt.IsNull()) && (DefaultAtt.ConstructorArguments.Count == 1))
{
ValueToReturn = DefaultAtt.ConstructorArguments[0].Value;
}
//If still no value found
if (ValueToReturn.IsNull())
{
//Trying to get the very first property of that enum
Array Values = Enum.GetValues(typeof(T));
//getting very first member of this enum
if (Values.Length > 0)
{
ValueToReturn = Values.GetValue(0);
}
}
//If any result found
if (!ValueToReturn.IsNull())
{
return (T)Enum.Parse(typeof(T), ValueToReturn.ToStringX());
}
return default(T);
}
Значением по умолчанию для типа перечисления является 0:
"По умолчанию первый перечислитель имеет значение 0, а значение каждого последующего перечислителя увеличивается на 1".
"Тип значения enum имеет значение, созданное выражением (E)0, где E - идентификатор перечисления".
Вы можете проверить документацию для перечисления C# здесь, а также документацию для таблицы значений C# по умолчанию здесь.
enum Orientations
{
None, North, East, South, West
}
private Orientations? _orientation { get; set; }
public Orientations? Orientation
{
get
{
return _orientation ?? Orientations.None;
}
set
{
_orientation = value;
}
}
Если вы установите для свойства значение null, будет возвращено значение Orientations.None при получении. Свойство _orientation по умолчанию имеет значение null.
Если вы определяете перечисление по умолчанию как перечисление с наименьшим значением, вы можете использовать это:
public enum MyEnum { His = -1, Hers = -2, Mine = -4, Theirs = -3 }
var firstEnum = ((MyEnum[])Enum.GetValues(typeof(MyEnum)))[0];
firstEnum == Mine.
Это не предполагает, что перечисление имеет нулевое значение.
The default is the first one in the definition. Например:
public enum MyEnum{His,Hers,Mine,Theirs}
Enum.GetValues(typeOf(MyEnum)).GetValue(0);
Это вернется His
В этом случае не полагайтесь на значение перечисления. Представьте метод расширения , затем вы можете использовать его так:
Orientation.North.ToInt32();
А вот код:
// Remove all the values from the enum
enum Orientation
{
None,
North,
East,
South,
West
}
public static class OrientationExtensions
{
public static int ToInt32(this Orientation orientation) => oritentation switch
{
case None => -1,
case North => 0,
case East => 1,
case South => 2,
case West => 3,
_ => throw new ArgumentOutOfRangeException(nameof(orientation), $"Not expected orientation value: {orientation}")
};
}
[DefaultValue(None)]
public enum Orientation
{
None = -1,
North = 0,
East = 1,
South = 2,
West = 3
}
Тогда в коде вы можете использовать
public Orientation GetDefaultOrientation()
{
return default(Orientation);
}