เป็นไปได้หรือไม่ที่จะกำหนดการแปลง enums โดยปริยายใน c #
สิ่งที่สามารถบรรลุนี้?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
ถ้าไม่เพราะเหตุใด
เป็นไปได้หรือไม่ที่จะกำหนดการแปลง enums โดยปริยายใน c #
สิ่งที่สามารถบรรลุนี้?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
ถ้าไม่เพราะเหตุใด
คำตอบ:
มีวิธีแก้ไข. พิจารณาสิ่งต่อไปนี้:
public sealed class AccountStatus
{
public static readonly AccountStatus Open = new AccountStatus(1);
public static readonly AccountStatus Closed = new AccountStatus(2);
public static readonly SortedList<byte, AccountStatus> Values = new SortedList<byte, AccountStatus>();
private readonly byte Value;
private AccountStatus(byte value)
{
this.Value = value;
Values.Add(value, this);
}
public static implicit operator AccountStatus(byte value)
{
return Values[value];
}
public static implicit operator byte(AccountStatus value)
{
return value.Value;
}
}
ข้างต้นเสนอการแปลงโดยปริยาย:
AccountStatus openedAccount = 1; // Works
byte openedValue = AccountStatus.Open; // Works
นี่เป็นงานที่ดีกว่าการประกาศ enum ปกติเล็กน้อย (แม้ว่าคุณสามารถ refactor บางส่วนข้างต้นเป็นคลาสพื้นฐานทั่วไปได้) คุณสามารถไปได้ไกลกว่านี้โดยให้คลาสพื้นฐานใช้ IComparable & IEquatable รวมถึงเพิ่มวิธีการคืนค่าของ DescriptionAttributes ชื่อที่ประกาศ ฯลฯ ฯลฯ
ฉันเขียนคลาสพื้นฐาน (RichEnum <>) เพื่อจัดการกับงานที่หนักหน่วงที่สุดซึ่งจะช่วยลดการประกาศ enums ข้างต้นลงไปที่:
public sealed class AccountStatus : RichEnum<byte, AccountStatus>
{
public static readonly AccountStatus Open = new AccountStatus(1);
public static readonly AccountStatus Closed = new AccountStatus(2);
private AccountStatus(byte value) : base (value)
{
}
public static implicit operator AccountStatus(byte value)
{
return Convert(value);
}
}
คลาสพื้นฐาน (RichEnum) แสดงอยู่ด้านล่าง
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
namespace Ethica
{
using Reflection;
using Text;
[DebuggerDisplay("{Value} ({Name})")]
public abstract class RichEnum<TValue, TDerived>
: IEquatable<TDerived>,
IComparable<TDerived>,
IComparable, IComparer<TDerived>
where TValue : struct , IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
#region Backing Fields
/// <summary>
/// The value of the enum item
/// </summary>
public readonly TValue Value;
/// <summary>
/// The public field name, determined from reflection
/// </summary>
private string _name;
/// <summary>
/// The DescriptionAttribute, if any, linked to the declaring field
/// </summary>
private DescriptionAttribute _descriptionAttribute;
/// <summary>
/// Reverse lookup to convert values back to local instances
/// </summary>
private static SortedList<TValue, TDerived> _values;
private static bool _isInitialized;
#endregion
#region Constructors
protected RichEnum(TValue value)
{
if (_values == null)
_values = new SortedList<TValue, TDerived>();
this.Value = value;
_values.Add(value, (TDerived)this);
}
#endregion
#region Properties
public string Name
{
get
{
CheckInitialized();
return _name;
}
}
public string Description
{
get
{
CheckInitialized();
if (_descriptionAttribute != null)
return _descriptionAttribute.Description;
return _name;
}
}
#endregion
#region Initialization
private static void CheckInitialized()
{
if (!_isInitialized)
{
ResourceManager _resources = new ResourceManager(typeof(TDerived).Name, typeof(TDerived).Assembly);
var fields = typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived));
foreach (var field in fields)
{
TDerived instance = (TDerived)field.GetValue(null);
instance._name = field.Name;
instance._descriptionAttribute = field.GetAttribute<DescriptionAttribute>();
var displayName = field.Name.ToPhrase();
}
_isInitialized = true;
}
}
#endregion
#region Conversion and Equality
public static TDerived Convert(TValue value)
{
return _values[value];
}
public static bool TryConvert(TValue value, out TDerived result)
{
return _values.TryGetValue(value, out result);
}
public static implicit operator TValue(RichEnum<TValue, TDerived> value)
{
return value.Value;
}
public static implicit operator RichEnum<TValue, TDerived>(TValue value)
{
return _values[value];
}
public static implicit operator TDerived(RichEnum<TValue, TDerived> value)
{
return value;
}
public override string ToString()
{
return _name;
}
#endregion
#region IEquatable<TDerived> Members
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.Equals((TValue)obj);
if (obj is TDerived)
return Value.Equals(((TDerived)obj).Value);
}
return false;
}
bool IEquatable<TDerived>.Equals(TDerived other)
{
return Value.Equals(other.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
#endregion
#region IComparable Members
int IComparable<TDerived>.CompareTo(TDerived other)
{
return Value.CompareTo(other.Value);
}
int IComparable.CompareTo(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.CompareTo((TValue)obj);
if (obj is TDerived)
return Value.CompareTo(((TDerived)obj).Value);
}
return -1;
}
int IComparer<TDerived>.Compare(TDerived x, TDerived y)
{
return (x == null) ? -1 :
(y == null) ? 1 :
x.Value.CompareTo(y.Value);
}
#endregion
public static IEnumerable<TDerived> Values
{
get
{
return _values.Values;
}
}
public static TDerived Parse(string name)
{
foreach (TDerived value in _values.Values)
if (0 == string.Compare(value.Name, name, true) || 0 == string.Compare(value.DisplayName, name, true))
return value;
return null;
}
}
}
คุณไม่สามารถทำการแปลงโดยนัย (ยกเว้นศูนย์) และคุณไม่สามารถเขียนวิธีการอินสแตนซ์ของคุณเองได้อย่างไรก็ตามคุณสามารถเขียนวิธีการขยายของคุณเองได้:
public enum MyEnum { A, B, C }
public static class MyEnumExt
{
public static int Value(this MyEnum foo) { return (int)foo; }
static void Main()
{
MyEnum val = MyEnum.A;
int i = val.Value();
}
}
สิ่งนี้ไม่ได้ให้อะไรคุณมากมายนัก (เทียบกับการแคสต์ที่ชัดเจน)
ครั้งสำคัญครั้งหนึ่งที่ฉันเคยเห็นผู้คนต้องการสิ่งนี้คือการ[Flags]
จัดการกับยาสามัญ - นั่นคือbool IsFlagSet<T>(T value, T flag);
วิธีการ น่าเสียดายที่ C # 3.0 ไม่รองรับตัวดำเนินการเกี่ยวกับ generics แต่คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดยใช้สิ่งต่างๆเช่นนี้ซึ่งทำให้ตัวดำเนินการพร้อมใช้งานกับ generics ได้อย่างเต็มที่
struct PseudoEnum
{
public const int
INPT = 0,
CTXT = 1,
OUTP = 2;
};
// ...
var arr = new String[3];
arr[PseudoEnum.CTXT] = "can";
arr[PseudoEnum.INPT] = "use";
arr[PseudoEnum.CTXT] = "as";
arr[PseudoEnum.CTXT] = "array";
arr[PseudoEnum.OUTP] = "index";
static class
ฉันคิดว่า ไม่มีข้อได้เปรียบในการโต้เถียงสำหรับทั้งสองกรณีในIL
รหัสสุดท้าย
ฉันปรับคลาสพื้นฐาน RichEnum ที่ยอดเยี่ยมของ Mark
แก้ไข
ขอชื่นชมสำหรับความคิดที่ยอดเยี่ยม + การใช้งานนี่คือสิ่งที่คุณทุกคน:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Resources;
namespace NMatrix
{
[DebuggerDisplay("{Value} ({Name})")]
public abstract class RichEnum<TValue, TDerived>
: IEquatable<TDerived>,
IComparable<TDerived>,
IComparable, IComparer<TDerived>
where TValue : struct, IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
#region Backing Fields
/// <summary>
/// The value of the enum item
/// </summary>
public readonly TValue Value;
/// <summary>
/// The public field name, determined from reflection
/// </summary>
private string _name;
/// <summary>
/// The DescriptionAttribute, if any, linked to the declaring field
/// </summary>
private DescriptionAttribute _descriptionAttribute;
/// <summary>
/// Reverse lookup to convert values back to local instances
/// </summary>
private static readonly SortedList<TValue, TDerived> _values = new SortedList<TValue, TDerived>();
#endregion
#region Constructors
protected RichEnum(TValue value)
{
this.Value = value;
_values.Add(value, (TDerived)this);
}
#endregion
#region Properties
public string Name
{
get
{
return _name;
}
}
public string Description
{
get
{
if (_descriptionAttribute != null)
return _descriptionAttribute.Description;
return _name;
}
}
#endregion
#region Initialization
static RichEnum()
{
var fields = typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived));
foreach (var field in fields)
{
/*var dummy =*/ field.GetValue(null); // forces static initializer to run for TDerived
TDerived instance = (TDerived)field.GetValue(null);
instance._name = field.Name;
instance._descriptionAttribute = field.GetCustomAttributes(true).OfType<DescriptionAttribute>().FirstOrDefault();
}
}
#endregion
#region Conversion and Equality
public static TDerived Convert(TValue value)
{
return _values[value];
}
public static bool TryConvert(TValue value, out TDerived result)
{
return _values.TryGetValue(value, out result);
}
public static implicit operator TValue(RichEnum<TValue, TDerived> value)
{
return value.Value;
}
public static implicit operator RichEnum<TValue, TDerived>(TValue value)
{
return _values[value];
}
public static implicit operator TDerived(RichEnum<TValue, TDerived> value)
{
return value;
}
public override string ToString()
{
return _name;
}
#endregion
#region IEquatable<TDerived> Members
public override bool Equals(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.Equals((TValue)obj);
if (obj is TDerived)
return Value.Equals(((TDerived)obj).Value);
}
return false;
}
bool IEquatable<TDerived>.Equals(TDerived other)
{
return Value.Equals(other.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
#endregion
#region IComparable Members
int IComparable<TDerived>.CompareTo(TDerived other)
{
return Value.CompareTo(other.Value);
}
int IComparable.CompareTo(object obj)
{
if (obj != null)
{
if (obj is TValue)
return Value.CompareTo((TValue)obj);
if (obj is TDerived)
return Value.CompareTo(((TDerived)obj).Value);
}
return -1;
}
int IComparer<TDerived>.Compare(TDerived x, TDerived y)
{
return (x == null) ? -1 :
(y == null) ? 1 :
x.Value.CompareTo(y.Value);
}
#endregion
public static IEnumerable<TDerived> Values
{
get
{
return _values.Values;
}
}
public static TDerived Parse(string name)
{
foreach (TDerived value in Values)
if (0 == string.Compare(value.Name, name, true))
return value;
return null;
}
}
}
ตัวอย่างการใช้งานที่ใช้กับระบบโมโน:
using System.ComponentModel;
using System;
namespace NMatrix
{
public sealed class MyEnum : RichEnum<int, MyEnum>
{
[Description("aap")] public static readonly MyEnum my_aap = new MyEnum(63000);
[Description("noot")] public static readonly MyEnum my_noot = new MyEnum(63001);
[Description("mies")] public static readonly MyEnum my_mies = new MyEnum(63002);
private MyEnum(int value) : base (value) { }
public static implicit operator MyEnum(int value) { return Convert(value); }
}
public static class Program
{
public static void Main(string[] args)
{
foreach (var enumvalue in MyEnum.Values)
Console.WriteLine("MyEnum {0}: {1} ({2})", (int) enumvalue, enumvalue, enumvalue.Description);
}
}
}
การผลิตเอาต์พุต
[mono] ~/custom/demo @ gmcs test.cs richenum.cs && ./test.exe
MyEnum 63000: my_aap (aap)
MyEnum 63001: my_noot (noot)
MyEnum 63002: my_mies (mies)
หมายเหตุ: mono 2.6.7 ต้องการการร่ายที่ชัดเจนเป็นพิเศษซึ่งไม่จำเป็นเมื่อใช้ mono 2.8.2 ...
FirstOrDefault
เพื่อหลีกเลี่ยงการสมมติว่ามีแอตทริบิวต์เดียวเท่านั้น) ไม่ว่าสิ่งนั้นจะเป็น 'ความคิดที่ดี' หรือไม่ (หรือไม่ดีสำหรับเรื่องนั้น) นั้นขึ้นอยู่กับบริบท
TDerived instance = (TDerived)field.GetValue(null);
ส่งผลให้instance
เป็นnull
. ดูเหมือนว่ารันไทม์ Mono ต้องมีลำดับการเริ่มต้นประเภทต่างจาก. NET ที่อนุญาตให้ทำงานได้ งง! ฉันต้องย้ายรหัสนั้นไปยังวิธีการแบบคงที่แทนและเรียกใช้จากประเภท initializer ในคลาสย่อย
คุณไม่สามารถประกาศการแปลงโดยนัยในประเภท enum ได้เนื่องจากไม่สามารถกำหนดวิธีการได้ คีย์เวิร์ดโดยนัย C # รวบรวมไว้ในเมธอดที่ขึ้นต้นด้วย 'op_' และจะใช้ไม่ได้ในกรณีนี้
คุณอาจทำได้ แต่ไม่ใช่สำหรับ enum (คุณไม่สามารถเพิ่มวิธีการได้) คุณสามารถเพิ่มการแปลงโดยนัยให้กับชั้นเรียนของคุณเองเพื่อให้สามารถแปลง enum ได้
public class MyClass {
public static implicit operator MyClass ( MyEnum input ) {
//...
}
}
MyClass m = MyEnum.One;
คำถามจะทำไม?
โดยทั่วไป. Net จะหลีกเลี่ยง (และคุณก็ควรเช่นกัน) การแปลงโดยปริยายใด ๆ ที่ข้อมูลอาจสูญหายได้
หากคุณกำหนดฐานของ enum เป็นความยาวคุณสามารถทำการแปลงอย่างชัดเจนได้ ฉันไม่รู้ว่าคุณสามารถใช้การแปลงโดยนัยได้หรือไม่เนื่องจาก enums ไม่สามารถกำหนดวิธีการได้
public enum MyEnum : long
{
one = 1,
two = 2,
}
MyEnum number = MyEnum.one;
long i = (long)number;
นอกจากนี้โปรดทราบด้วยว่าการแจงนับที่ไม่ได้ระบุค่าเริ่มต้นจะเป็นค่าเริ่มต้นเป็นค่า 0 หรือรายการแรกดังนั้นในสถานการณ์ข้างต้นจึงควรกำหนดzero = 0
ด้วยเช่นกัน
: long
นี่ การแปลงอย่างชัดเจนจะทำงานได้ดีหากไม่มีมัน การแปลงโดยนัยทางกฎหมายเพียงอย่างเดียวคือศูนย์
enums ส่วนใหญ่ไร้ประโยชน์สำหรับฉันเพราะเหตุนี้ OP
ฉันจบลงด้วยการทำภาพที่เกี่ยวข้องตลอดเวลา:
ปัญหาตัวอย่างคลาสสิกคือชุด VirtualKey สำหรับตรวจจับการกดแป้นพิมพ์
enum VKeys : ushort
{
a = 1,
b = 2,
c = 3
}
// the goal is to index the array using predefined constants
int[] array = new int[500];
var x = array[VKeys.VK_LSHIFT];
ปัญหาที่นี่คือคุณไม่สามารถจัดทำดัชนีอาร์เรย์ด้วย enum ได้เนื่องจากไม่สามารถแปลง enum เป็น ushort โดยปริยายได้ (แม้ว่าเราจะใช้ enum ใน ushort)
ในบริบทเฉพาะนี้ enums จะล้าสมัยโดยโครงสร้างข้อมูลต่อไปนี้ . . .
public static class VKeys
{
public const ushort
a = 1,
b = 2,
c = 3;
}
ฉันได้แก้ไขปัญหาเกี่ยวกับคำตอบของ seheเมื่อเรียกใช้รหัสบน MS .net (ไม่ใช่ Mono) สำหรับฉันโดยเฉพาะปัญหาเกิดขึ้นบน. net 4.5.1 แต่ดูเหมือนว่าเวอร์ชันอื่น ๆ จะได้รับผลกระทบเช่นกัน
การเข้าถึงpublic static TDervied MyEnumValue
โดยการสะท้อนกลับ (ผ่านFieldInfo.GetValue(null)
ไม่ได้เริ่มต้นฟิลด์ดังกล่าว
แทนการกำหนดชื่อTDerived
อินสแตนซ์เมื่อ initializer คงที่ของนี้จะทำอย่างเฉื่อยชาในการเข้าถึงแรกของRichEnum<TValue, TDerived>
TDerived.Name
รหัส:
public abstract class RichEnum<TValue, TDerived> : EquatableBase<TDerived>
where TValue : struct, IComparable<TValue>, IEquatable<TValue>
where TDerived : RichEnum<TValue, TDerived>
{
// Enforcing that the field Name (´SomeEnum.SomeEnumValue´) is the same as its
// instances ´SomeEnum.Name´ is done by the static initializer of this class.
// Explanation of initialization sequence:
// 1. the static initializer of ´RichEnum<TValue, TDerived>´ reflects TDervied and
// creates a list of all ´public static TDervied´ fields:
// ´EnumInstanceToNameMapping´
// 2. the static initializer of ´TDerive´d assigns values to these fields
// 3. The user is now able to access the values of a field.
// Upon first access of ´TDervied.Name´ we search the list
// ´EnumInstanceToNameMapping´ (created at step 1) for the field that holds
// ´this´ instance of ´TDerived´.
// We then get the Name for ´this´ from the FieldInfo
private static readonly IReadOnlyCollection<EnumInstanceReflectionInfo>
EnumInstanceToNameMapping =
typeof(TDerived)
.GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public)
.Where(t => t.FieldType == typeof(TDerived))
.Select(fieldInfo => new EnumInstanceReflectionInfo(fieldInfo))
.ToList();
private static readonly SortedList<TValue, TDerived> Values =
new SortedList<TValue, TDerived>();
public readonly TValue Value;
private readonly Lazy<string> _name;
protected RichEnum(TValue value)
{
Value = value;
// SortedList doesn't allow duplicates so we don't need to do
// duplicate checking ourselves
Values.Add(value, (TDerived)this);
_name = new Lazy<string>(
() => EnumInstanceToNameMapping
.First(x => ReferenceEquals(this, x.Instance))
.Name);
}
public string Name
{
get { return _name.Value; }
}
public static implicit operator TValue(RichEnum<TValue, TDerived> richEnum)
{
return richEnum.Value;
}
public static TDerived Convert(TValue value)
{
return Values[value];
}
protected override bool Equals(TDerived other)
{
return Value.Equals(other.Value);
}
protected override int ComputeHashCode()
{
return Value.GetHashCode();
}
private class EnumInstanceReflectionInfo
{
private readonly FieldInfo _field;
private readonly Lazy<TDerived> _instance;
public EnumInstanceReflectionInfo(FieldInfo field)
{
_field = field;
_instance = new Lazy<TDerived>(() => (TDerived)field.GetValue(null));
}
public TDerived Instance
{
get { return _instance.Value; }
}
public string Name { get { return _field.Name; } }
}
}
ซึ่ง - ในกรณีของฉัน - ขึ้นอยู่กับEquatableBase<T>
:
public abstract class EquatableBase<T>
where T : class
{
public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}
T other = obj as T;
if (other == null)
{
return false;
}
return Equals(other);
}
protected abstract bool Equals(T other);
public override int GetHashCode()
{
unchecked
{
return ComputeHashCode();
}
}
protected abstract int ComputeHashCode();
}
โค้ดข้างต้นไม่ได้รวมคุณสมบัติทั้งหมดของคำตอบเดิมของMark !
ขอขอบคุณที่มาร์คสำหรับการให้บริการของเขาRichEnum
ดำเนินการและขอขอบคุณที่seheสำหรับการให้บริการการปรับปรุงบางอย่าง!
ฉันพบวิธีแก้ปัญหาที่ง่ายยิ่งขึ้นจากที่นี่/codereview/7566/enum-vs-int-wrapper-structฉันวางโค้ดด้านล่างจากลิงค์นั้นในกรณีที่ไม่สามารถใช้งานได้ในอนาคต
struct Day
{
readonly int day;
public static readonly Day Monday = 0;
public static readonly Day Tuesday = 1;
public static readonly Day Wednesday = 2;
public static readonly Day Thursday = 3;
public static readonly Day Friday = 4;
public static readonly Day Saturday = 5;
public static readonly Day Sunday = 6;
private Day(int day)
{
this.day = day;
}
public static implicit operator int(Day value)
{
return value.day;
}
public static implicit operator Day(int value)
{
return new Day(value);
}
}
ฉันสร้างอรรถประโยชน์นี้จะช่วยให้ฉันแปลงEnumเพื่อPrimitiveEnumและPrimitiveEnumbyte, sbyte, short, ushort, int, uint, long, or ulong
ไป
ดังนั้นในทางเทคนิคแล้วสิ่งนี้จะแปลง enum เป็นค่าดั้งเดิม
public enum MyEnum
{
one = 1, two = 2
}
PrimitiveEnum number = MyEnum.one;
long i = number;
using System;
namespace McKabue.Extentions.Utility.Enums
{
/// <summary>
/// <see href="https://stackoverflow.com/q/261663/3563013">
/// Can we define implicit conversions of enums in c#?
/// </see>
/// </summary>
public struct PrimitiveEnum
{
private Enum _enum;
public PrimitiveEnum(Enum _enum)
{
this._enum = _enum;
}
public Enum Enum => _enum;
public static implicit operator PrimitiveEnum(Enum _enum)
{
return new PrimitiveEnum(_enum);
}
public static implicit operator Enum(PrimitiveEnum primitiveEnum)
{
return primitiveEnum.Enum;
}
public static implicit operator byte(PrimitiveEnum primitiveEnum)
{
return Convert.ToByte(primitiveEnum.Enum);
}
public static implicit operator sbyte(PrimitiveEnum primitiveEnum)
{
return Convert.ToSByte(primitiveEnum.Enum);
}
public static implicit operator short(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt16(primitiveEnum.Enum);
}
public static implicit operator ushort(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt16(primitiveEnum.Enum);
}
public static implicit operator int(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt32(primitiveEnum.Enum);
}
public static implicit operator uint(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt32(primitiveEnum.Enum);
}
public static implicit operator long(PrimitiveEnum primitiveEnum)
{
return Convert.ToInt64(primitiveEnum.Enum);
}
public static implicit operator ulong(PrimitiveEnum primitiveEnum)
{
return Convert.ToUInt64(primitiveEnum.Enum);
}
}
}
uint
s ซึ่งเกมนั้นมักจะสร้างมาenum
เพื่อ แต่เฟรมเวิร์กนั้นไม่รู้อะไรเลย เมื่อต้อง(uint)
เรียกเฟรมเวิร์กเป็นความเจ็บปวด ความคิดของคุณย้อนกลับทำงานได้อย่างสมบูรณ์ แทนที่จะstruct
จัดเก็บEnum
ฉันมีstruct IdNumber
ที่เก็บuint
แต่โดยปริยายแปลงจากEnum
เกมที่ใช้ แทนที่จะพิมพ์พารามิเตอร์ของเฟรมเวิร์กเป็นuint
ฉันสามารถพิมพ์ได้IdNumber
และเฟรมเวิร์กสามารถส่งผ่านสิ่งเหล่านี้ไปได้ภายในอย่างมีประสิทธิภาพแม้กระทั่งการดำเนินการที่สำคัญ
การแนะนำการแปลงโดยนัยสำหรับประเภท enum จะทำลายความปลอดภัยของประเภทดังนั้นฉันไม่แนะนำให้ทำเช่นนั้น ทำไมคุณถึงอยากทำเช่นนั้น? กรณีการใช้งานเดียวที่ฉันเคยเห็นคือเมื่อคุณต้องการใส่ค่า enum ลงในโครงสร้างที่มีเค้าโครงที่กำหนดไว้ล่วงหน้า แต่ถึงอย่างนั้นคุณสามารถใช้ enum type ในโครงสร้างและบอก Marshaller ว่าเขาควรทำอย่างไรกับสิ่งนี้
enum YesNo {Yes, No}
ที่สามารถแปลงเป็น bool ได้โดยปริยาย