รับค่า int จาก enum ใน C #


1822

ฉันมีชั้นเรียนที่เรียกว่าQuestions(พหูพจน์) ในชั้นเรียนนี้มี enum เรียกว่าQuestion(เอกพจน์) ซึ่งมีลักษณะเช่นนี้

public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

ในQuestionsระดับฉันมีget(int foo)ฟังก์ชั่นที่ส่งกลับวัตถุที่Questions fooมีวิธีง่ายๆในการดึงค่าจำนวนเต็มออกจาก enum เพื่อที่ฉันจะทำอะไรแบบนี้Questions.Get(Question.Role)?


31
สำหรับวิธีอื่น ๆ : หล่อ int เพื่อ enum ใน-C-คม
nawfal

11
ฉันรู้ว่าฉันมางานปาร์ตี้ แต่แทนที่จะกำหนดวิธีการของคุณในขณะที่get(int foo)คุณสามารถกำหนดมันget(Question foo)แล้วทำการคัดเลือกภายในวิธีการที่คุณสามารถเรียกวิธีการของคุณเป็นQuestions.Get(Question.Role)
Joe

คำตอบ:


2351

เพียงแค่โยน enum เช่น

int something = (int) Question.Role;

การทำงานจะข้างต้นสำหรับส่วนใหญ่ของ enums ที่คุณเห็นในป่าเป็นชนิดพื้นฐานเริ่มต้นสำหรับ Enum intที่เป็น

อย่างไรก็ตามในขณะที่เซซิลฟิลลิปชี้ให้เห็น enums สามารถมีประเภทพื้นฐานที่แตกต่างกัน ถ้า enum ถูกประกาศว่าเป็นuint,, longหรือulong, มันควรถูกนำไปใช้กับประเภทของ enum; เช่นสำหรับ

enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};

คุณควรใช้

long something = (long)StarsInMilkyWay.Wolf424B;

23
@Harry มันไม่เป็นความจริง คุณสามารถสร้างการแจงนับโดยไม่ต้องแคสมันไม่จำเป็น และฉันกำหนดหมายเลขเฉพาะในกรณีพิเศษโดยส่วนใหญ่แล้วฉันจะปล่อยไว้เป็นค่าเริ่มต้น แต่คุณสามารถทำได้enum Test { Item = 1 }และดูว่า1 == (int)Test.Itemเท่ากัน
Jaider

33
@Jaider (int)Test.Itemนั่นคือนักแสดง! () เป็นตัวดำเนินการส่งที่ชัดเจน
Sinthia V

48
@Sinthia V เขาบอกว่าคุณสามารถสร้างได้โดยไม่ต้องหล่อซึ่งถูกต้อง
Paul Ridgway

7
ถ้าประเภทพื้นฐานของenum Questionไม่ได้intแต่longนักแสดงนี้จะตัดทอนRoleมูลค่ารวมของ!
quaylar

1
เมื่อคุณยอมรับEnumพารามิเตอร์ในฐานะที่คุณรู้ว่าเป็นเพียงจำนวนคงที่ของค่าอินทิกรัลที่เป็นไปได้ที่คุณจะได้รับ ในทางกลับกันถ้าคุณเพียงแค่intคุณต้องตรวจสอบว่าintมันอยู่ในค่าที่ยอมรับได้ดังนั้นจึงทำให้รหัสซับซ้อน คุณสามารถลบล้างลายเซ็นของคุณเช่น `` `public void MyMethod (int x) {// ทำอะไรกับ x} public void MyMethod (Enum x) {this.MyMethod ((int) x); } `` ``
recognbus

307

ตั้งแต่ Enums สามารถเป็นประเภทหนึ่งใด ๆ ( byte, int, shortฯลฯ ) เป็นวิธีที่มีประสิทธิภาพมากขึ้นเพื่อให้ได้ค่าที่สำคัญพื้นฐานของ enum จะทำให้การใช้งานของGetTypeCodeวิธีการในการร่วมกับConvertระดับ:

enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);

สิ่งนี้จะทำงานได้โดยไม่คำนึงถึงประเภทอินทิกรัลพื้นฐาน


32
เทคนิคนี้พิสูจน์แล้วว่าคุ้มค่าสำหรับฉันเมื่อต้องรับมือกับประเภททั่วไปที่ T: enum (จริง ๆ แล้ว T: struct, IConvertible แต่นั่นเป็นเรื่องที่แตกต่างกัน)
aboy021

1
คุณจะแก้ไขสิ่งนี้เพื่อพิมพ์ค่าเลขฐานสิบหกของด้านข้างได้อย่างไร ตัวอย่างนี้แสดงค่าทศนิยม ปัญหาคือว่าvarเป็นประเภทobjectดังนั้นคุณต้องปลดกล่องออกและมันจะเลอะกว่าที่ฉันต้องการ
ทำเครื่องหมาย Lakata

2
ฉันคิดว่าคุณควรเปลี่ยนตัวอย่างเพื่อในตัวอย่างของคุณจะเป็น object val = Convert...etcvarobject
ตาข่าย

2
@TimAbell ทั้งหมดที่ฉันสามารถพูดได้ก็คือเราพบว่าเพจ aspx ที่รวบรวมแบบไดนามิก (ที่คุณต้องปรับใช้ไฟล์. cs ไปยังเซิร์ฟเวอร์สด) ได้กำหนดจำนวนเต็มแตกต่างกันไปตามแต่ละค่า นั่นหมายความว่าวัตถุที่เป็นอนุกรมหนึ่งเครื่องถูก deserialising ด้วยค่าที่แตกต่างกันบนเครื่องที่แตกต่างกันและเสียหายอย่างมีประสิทธิภาพ (ทำให้เกิดความสับสนหลายชั่วโมง ) เรายกมันขึ้นด้วย MS และฉันดูเหมือนจะจำได้ว่าพวกเขาบอกว่าจำนวนเต็มที่สร้างอัตโนมัติไม่ได้รับประกันว่าจะเหมือนกันเมื่อสร้างในกรอบงานเวอร์ชันที่แตกต่างกัน
NickG

4
@TimAbell ในบางโอกาสผู้พัฒนาได้ลบค่า Enum ที่ล้าสมัย / ไม่ได้ใช้ซึ่งทำให้ค่าอื่น ๆ ทั้งหมดในลำดับถูกลบออกโดยหนึ่ง ด้วยเหตุนี้มาตรฐานการเข้ารหัสของเราจึงกำหนดให้ ID ต้องระบุอย่างชัดเจนเสมอมิฉะนั้นการเพิ่ม / ลบหรือแม้แต่การจัดรูปแบบรหัสอัตโนมัติ (เช่นการเรียงลำดับตามตัวอักษร) จะเปลี่ยนค่าทั้งหมดที่ทำให้ข้อมูลเสียหาย ฉันขอแนะนำให้ทุกคนระบุจำนวนเต็ม Enum ทั้งหมดอย่างชัดเจน สิ่งนี้มีความสำคัญมากหากมันสัมพันธ์กับค่าที่จัดเก็บภายนอก (ฐานข้อมูล)
NickG

199

ประกาศว่าเป็นคลาสที่มีค่าคงที่แบบสาธารณะ:

public static class Question
{
    public const int Role = 2;
    public const int ProjectFunding = 3;
    public const int TotalEmployee = 4;
    public const int NumberOfServers = 5;
    public const int TopBusinessConcern = 6;
}

จากนั้นคุณสามารถอ้างอิงมันได้Question.Roleและมันจะประเมินค่าเป็นintหรืออะไรก็ตามที่คุณนิยามว่าเป็น


31
ฉันจะใช้static readonly intเพราะค่าคงที่นั้นเรียบเรียงเป็นค่าแข็ง ดูstackoverflow.com/a/755693/492
CAD bloke

96
การแก้ปัญหานี้จริง ๆ แล้วไม่ให้ประโยชน์ที่แท้จริงของ enums ที่พิมพ์อย่างมาก หากฉันเพียงต้องการส่งผ่าน GameState-enum-parameter ไปยังวิธีการเฉพาะเช่นคอมไพเลอร์ไม่ควรอนุญาตให้ฉันผ่านตัวแปร int ใด ๆ เป็นพารามิเตอร์
thgc

12
@CADBloke ซึ่งเป็นเหตุผลที่คุณจะใช้constและไม่ใช่static readonlyเพราะทุกครั้งที่คุณเปรียบเทียบstatic readonlyคุณกำลังทำการเรียกเมธอดเพื่อรับค่าของตัวแปรขณะที่constคุณกำลังเปรียบเทียบสองประเภทค่าโดยตรง
blockloop

3
@ brettof86 ใช่ const จะเร็วขึ้นหากข้อ จำกัด การรวบรวมจะไม่เป็นปัญหาแล้วมันก็ดี
CAD bloke

2
@ แซคฉันไม่ได้อธิบายว่าดีมากโดยcompilation limitationฉันหมายความว่าค่านั้นเป็นรหัสที่ยากเมื่อคุณคอมไพล์ดังนั้นการเปลี่ยนแปลงใด ๆ กับค่านั้นจะต้องให้แอสเซมบลีทั้งหมดที่ใช้มันจำเป็นต้องทำการคอมไพล์ใหม่ ฉันอยากจะเห็นด้วยกับคุณเกี่ยวกับการใช้งานเพราะการเปลี่ยนแปลงค่าจะมีผลกระทบอย่างกว้างขวาง
คนเจ้าเล่ห์ CAD

87
Question question = Question.Role;
int value = (int) question;

value == 2จะส่งผลให้


34
คำถามตัวแปรชั่วคราวนั้นไม่จำเป็น
Gishu

1
ดังนั้นบางอย่างเช่นนี้ Questions.Get (Convert.ToInt16 (Question.Applications))
จิม

6
คุณสามารถโยนในทิศทางใดก็ได้ สิ่งเดียวที่ต้องดูคือว่า enums ไม่ได้บังคับอะไรเลย (enum ค่าที่อาจจะ 288 แม้ว่าจะไม่มีคำถามที่จะเกิดขึ้นกับตัวเลขที่)
Marc Gravell

@jim: ไม่เพียงแค่โยนค่า: Questions.Get ((int) Question.Applications);
Guffa

1
@Gishu คุณสามารถพูดได้ว่า ... น่าสงสัย ;)
เฟลิกซ์ดี.

79

ในบันทึกที่เกี่ยวข้องถ้าคุณต้องการรับintค่าจากSystem.Enumนั้นให้eที่นี่:

Enum e = Question.Role;

คุณสามารถใช้ได้:

int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);

สองคนสุดท้ายน่าเกลียดธรรมดา ฉันชอบอันแรก


1
อย่างที่สองคือเร็วที่สุดแม้ว่า
Johan B

1
ในฐานะที่เป็นคนที่คุ้นเคยกับการใช้ Mixins ในการ modding ของ Minecraft สิ่งที่สองดูเหมือนจะเป็นผู้ชนะที่ชัดเจน
Sollace

40

ง่ายกว่าที่คุณคิด enum นั้นเป็น int อยู่แล้ว มันแค่ต้องได้รับการเตือน:

int y = (int)Question.Role;
Console.WriteLine(y); // Prints 2

15
nitpick: นี้ enum อยู่แล้ว int Enums อื่น ๆ อาจเป็นประเภทที่แตกต่างกัน - ลอง "enum SmallEnum: byte {A, B, C}"
mqp

9
จริงที่สุด. การอ้างอิง C #: "ทุกประเภทการแจงนับมีประเภทพื้นฐานซึ่งสามารถเป็นประเภทที่สำคัญใด ๆ ยกเว้นถ่าน"
Michael Petrotta

33

ตัวอย่าง:

public Enum EmpNo
{
    Raj = 1,
    Rahul,
    Priyanka
}

และในโค้ดด้านหลังเพื่อรับค่า enum:

int setempNo = (int)EmpNo.Raj; // This will give setempNo = 1

หรือ

int setempNo = (int)EmpNo.Rahul; // This will give setempNo = 2

Enums จะเพิ่มขึ้น 1 และคุณสามารถตั้งค่าเริ่มต้น หากคุณไม่ได้ตั้งค่าเริ่มต้นมันจะถูกกำหนดเป็น 0 เริ่มต้น


6
สิ่งนี้รวบรวมได้จริงหรือ?
Peter Mortensen

สิ่งที่เป็นราชาสามารถเป็นราหุลหรือ Priyanka ได้หรือไม่? ค่านิยมของคุณขัดแย้งกันและควรเพิ่มเป็นสองเท่าเช่น 0, 1, 2, 4, 8 เป็นต้นนี่เป็นข้อกังวลหลักของฉันกับ enums
Timothy Gonzalez

@TimothyGonzalez จริง ๆ แล้ว enums เพียงแค่นับ 1 ขึ้นถ้าคุณไม่ได้ระบุค่าของพวกเขาอย่างชัดเจน;)
30914

@derHugo ที่ขึ้นอยู่กับว่าคุณคิดว่าค่าตัวเลขเป็นฐาน 10 หรือฐาน 2
Timothy Gonzalez

@ TimothyGonzalez มีไม่มากที่จะคิด ... ฉันแค่ชี้ให้เห็นว่าโดยค่าเริ่มต้นพวกเขาเพียงแค่นับ1ในintยกเว้นว่าคุณกำหนดไว้เป็นอย่างอื่นอย่างชัดเจน
derHugo

28

ฉันเพิ่งแปลงออกจากการใช้ enums ในรหัสของฉันแทนการใช้คลาสกับตัวสร้างที่มีการป้องกันและอินสแตนซ์ที่กำหนดไว้ล่วงหน้า (ขอบคุณ Roelof - C # ตรวจสอบค่า Enum ที่ถูกต้อง - วิธี Futureproof )

ในแง่ของการที่ด้านล่างของวิธีการที่ฉันต้องการตอนนี้วิธีการแก้ไขปัญหานี้ (รวมถึงการแปลงโดยปริยายจาก / ไปint)

public class Question
{
    // Attributes
    protected int index;
    protected string name;
    // Go with a dictionary to enforce unique index
    //protected static readonly ICollection<Question> values = new Collection<Question>();
    protected static readonly IDictionary<int,Question> values = new Dictionary<int,Question>();

    // Define the "enum" values
    public static readonly Question Role = new Question(2,"Role");
    public static readonly Question ProjectFunding = new Question(3, "Project Funding");
    public static readonly Question TotalEmployee = new Question(4, "Total Employee");
    public static readonly Question NumberOfServers = new Question(5, "Number of Servers");
    public static readonly Question TopBusinessConcern = new Question(6, "Top Business Concern");

    // Constructors
    protected Question(int index, string name)
    {
        this.index = index;
        this.name = name;
        values.Add(index, this);
    }

    // Easy int conversion
    public static implicit operator int(Question question) =>
        question.index; //nb: if question is null this will return a null pointer exception

    public static implicit operator Question(int index) =>        
        values.TryGetValue(index, out var question) ? question : null;

    // Easy string conversion (also update ToString for the same effect)
    public override string ToString() =>
        this.name;

    public static implicit operator string(Question question) =>
        question?.ToString();

    public static implicit operator Question(string name) =>
        name == null ? null : values.Values.FirstOrDefault(item => name.Equals(item.name, StringComparison.CurrentCultureIgnoreCase));


    // If you specifically want a Get(int x) function (though not required given the implicit converstion)
    public Question Get(int foo) =>
        foo; //(implicit conversion will take care of the conversion for you)
}

ข้อดีของวิธีนี้คือคุณได้ทุกอย่างที่คุณมีจาก enum แต่ตอนนี้โค้ดของคุณมีความยืดหยุ่นมากขึ้นดังนั้นหากคุณต้องการดำเนินการต่าง ๆ ตามมูลค่าของQuestionคุณสามารถใส่ตรรกะลงในQuestionตัวเอง (เช่นใน OO ที่ต้องการ แฟชั่น) ซึ่งแตกต่างจากการวางคำสั่งกรณีจำนวนมากในรหัสของคุณเพื่อแก้ไขปัญหาในแต่ละสถานการณ์


NB: คำตอบอัพเดท 2018-04-27 เพื่อใช้ประโยชน์จากคุณสมบัติ C # 6; เช่นการประกาศการแสดงออกและคำจำกัดความการแสดงออกของแลมบ์ดา ดูประวัติการแก้ไขรหัสต้นฉบับ นี่มีประโยชน์ในการทำให้คำจำกัดความน้อย verbose; ซึ่งเป็นหนึ่งในข้อร้องเรียนหลักเกี่ยวกับวิธีการของคำตอบนี้


2
ฉันเดาว่ามันเป็นการแลกเปลี่ยนระหว่างนักแสดงที่ชัดเจนกับโค้ดที่คุณต้องเขียนเพื่อหลีกเลี่ยงมัน ยังคงรักการใช้งานเพียงแค่หวังว่ามันจะไม่ยาวมาก +1
Lankymart

3
ฉันใช้คลาสที่แตกต่างกันหลายแบบซึ่งมีโครงสร้างคล้ายกับนี้ ฉันพบว่าพวกเขาทำงานอย่างมหัศจรรย์เมื่อพยายามทำตามวิธี "อย่าให้ฉันเป็นคนบ้าในภายหลัง"
James Haug

20

หากคุณต้องการรับจำนวนเต็มสำหรับค่า enum ที่เก็บไว้ในตัวแปรซึ่งเป็นประเภทที่จะQuestionใช้เป็นตัวอย่างในวิธีการคุณสามารถทำสิ่งนี้ฉันเขียนในตัวอย่างนี้:

enum Talen
{
    Engels = 1, Italiaans = 2, Portugees = 3, Nederlands = 4, Duits = 5, Dens = 6
}

Talen Geselecteerd;    

public void Form1()
{
    InitializeComponent()
    Geselecteerd = Talen.Nederlands;
}

// You can use the Enum type as a parameter, so any enumeration from any enumerator can be used as parameter
void VeranderenTitel(Enum e)
{
    this.Text = Convert.ToInt32(e).ToString();
}

นี้จะเปลี่ยนชื่อหน้าต่าง 4 เพราะตัวแปรคือGeselecteerd Talen.Nederlandsถ้าฉันเปลี่ยนเป็นTalen.Portugeesและเรียกวิธีการอีกครั้งข้อความจะเปลี่ยนเป็น 3


3
การเข้ารหัสในดัตช์ โอ้ที่รัก
WiseStrawberry

น่าเสียดายที่วิธีการนี้ให้ประสิทธิภาพที่ต่ำกว่าที่คุณใช้ ฉันลองมันในโค้ดของฉันและเมื่อเวลาผ่านไปแอปพลิเคชันของฉันก็ช้าลงและช้าลงด้วยการใช้งาน CPU ที่น้อยลง สิ่งนี้บ่งบอกว่าเธรดกำลังรอบางสิ่ง - ฉันสมมติว่ามีการรวบรวมขยะบางประเภทอาจเป็นเพราะการมวยพารามิเตอร์ enum เป็น ToInt32 () ด้วยการสลับไปใช้ int.Parse () แบบง่ายฉันสามารถกำจัดประสิทธิภาพที่ไม่ดีนี้ได้อย่างสมบูรณ์และประสิทธิภาพยังคงเหมือนเดิมไม่ว่ารหัสจะรันนานแค่ไหน
เกร็ก

16

เพื่อให้แน่ใจว่ามีค่า enum อยู่แล้วแยกวิเคราะห์คุณยังสามารถทำสิ่งต่อไปนี้

// Fake Day of Week
string strDOWFake = "SuperDay";

// Real Day of Week
string strDOWReal = "Friday";

// Will hold which ever is the real DOW.
DayOfWeek enmDOW;

// See if fake DOW is defined in the DayOfWeek enumeration.
if (Enum.IsDefined(typeof(DayOfWeek), strDOWFake))
{
    // This will never be reached since "SuperDay"
    // doesn't exist in the DayOfWeek enumeration.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWFake);
}
// See if real DOW is defined in the DayOfWeek enumeration.
else if (Enum.IsDefined(typeof(DayOfWeek), strDOWReal))
{
    // This will parse the string into it's corresponding DOW enum object.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWReal);
}

// Can now use the DOW enum object.
Console.Write("Today is " + enmDOW.ToString() + ".");

14

บางทีฉันอาจจะพลาด แต่มีใครลองวิธีการทั่วไปอย่างง่าย ๆ หรือไม่?

มันใช้งานได้ดีสำหรับฉัน คุณสามารถหลีกเลี่ยงการส่งชนิดใน API ของคุณด้วยวิธีนี้ แต่ในที่สุดจะส่งผลในการดำเนินการเปลี่ยนประเภท นี่เป็นกรณีที่ดีสำหรับการเขียนโปรแกรมRoslynเพื่อให้คอมไพเลอร์สร้างเมธอด GetValue <T> ให้คุณ

    public static void Main()
    {
        int test = MyCSharpWrapperMethod(TestEnum.Test1);

        Debug.Assert(test == 1);
    }

    public static int MyCSharpWrapperMethod(TestEnum customFlag)
    {
        return MyCPlusPlusMethod(customFlag.GetValue<int>());
    }

    public static int MyCPlusPlusMethod(int customFlag)
    {
        // Pretend you made a PInvoke or COM+ call to C++ method that require an integer
        return customFlag;
    }

    public enum TestEnum
    {
        Test1 = 1,
        Test2 = 2,
        Test3 = 3
    }
}

public static class EnumExtensions
{
    public static T GetValue<T>(this Enum enumeration)
    {
        T result = default(T);

        try
        {
            result = (T)Convert.ChangeType(enumeration, typeof(T));
        }
        catch (Exception ex)
        {
            Debug.Assert(false);
            Debug.WriteLine(ex);
        }

        return result;
    }
}

อาจเป็นเพราะการทำ customFlag (int) พิมพ์น้อยลงและทำสิ่งเดียวกันมากขึ้นหรือน้อยลง?
Tim Keating

เรื่อง"บางทีฉันอาจจะพลาดมันมี แต่คนพยายามทั่วไปง่ายวิธีขยาย ?" : SixOThree กล่าวว่า "ใช้วิธีขยายแทน"และBronek กล่าวว่า "คุณสามารถทำเช่นนี้โดยการใช้วิธีขยายประเภท enum กำหนดไว้ของคุณ"
Peter Mortensen

13

อีกวิธีหนึ่งในการทำ:

Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);

มันจะส่งผลใน:

Name: Role, Value: 2

12
public enum QuestionType
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

... เป็นการประกาศที่ดี

คุณต้องส่งผลลัพธ์ให้เหมือนดังนี้:

int Question = (int)QuestionType.Role

มิฉะนั้นชนิดจะยังคงQuestionTypeอยู่

ความเข้มงวดระดับนี้เป็นวิธี C #

ทางเลือกหนึ่งคือใช้การประกาศคลาสแทน:

public class QuestionType
{
    public static int Role = 2,
    public static int ProjectFunding = 3,
    public static int TotalEmployee = 4,
    public static int NumberOfServers = 5,
    public static int TopBusinessConcern = 6
}

มันสวยงามน้อยกว่าที่จะประกาศ แต่คุณไม่จำเป็นต้องโยนมันในโค้ด:

int Question = QuestionType.Role

หรือคุณอาจรู้สึกสบายใจกับ Visual Basic ซึ่งเหมาะสำหรับความคาดหวังประเภทนี้ในหลายพื้นที่


11
int number = Question.Role.GetHashCode();

number2ควรจะมีค่า


GetHashCode เป็นวิธีหนึ่งในการรับค่าจากหน้ากากทั่วไปของ Enum
ThanhLD

หมายเหตุว่านี้เป็นเพียง "Legit" สำหรับbool* byte, ushort, intและuint** GetHashCode สำหรับประเภทอื่น ๆ ปรับเปลี่ยนค่าเช่นทำบางบิตกะและ xors (* 1/0, ** ไปที่ int แน่นอน) แต่ทั้งหมดไม่ได้ทำเช่นนี้เว้นแต่ว่าเป็นรหัสส่วนตัวของคุณเอง
AnorZaken

10

คุณสามารถทำได้โดยการนำวิธีการขยายไปใช้กับประเภท enum ที่คุณกำหนด:

public static class MyExtensions
{
    public static int getNumberValue(this Question questionThis)
    {
        return (int)questionThis;
    }
}

สิ่งนี้ทำให้การรับค่า int ของค่า enum ง่ายขึ้น:

Question question = Question.Role;
int value = question.getNumberValue();

หรือ

int value = Question.Role.getNumberValue();

5
ก่อนหน้านี้สิ่งที่คุณทำคือสร้างไวยากรณ์ที่ผิดปกติผ่านวิธีการขยาย (ไม่ใช่ btw ทั่วไป) ที่ใช้เวลาเขียนนานกว่า ฉันล้มเหลวในการดูว่าดีกว่าโซลูชันดั้งเดิมของ Tetraneutron อย่างไร อย่าให้เราทำสิ่งนี้ในการแชทเรายินดีให้ความช่วยเหลือเสมอใน stackoverflow และทุกคนที่นี่พร้อมให้ความช่วยเหลือ โปรดใช้ความคิดเห็นของฉันเป็นคำวิจารณ์ที่สร้างสรรค์
Benjamin Gruenbaum

2
เบ็นจามินก่อนอื่นทำไมคุณลบความคิดเห็นของฉันฉันไม่เข้าใจการตัดสินใจของคุณ - บางทีคนอื่น ๆ ในชุมชนจะเห็นด้วยกับความคิดเห็นของฉันประการที่สองโซลูชันของฉันครอบคลุมหนึ่งของ Tetraneutron และแม่นยำกว่า แนะนำวิธีการขยายโดย IntelliSense ดังนั้นฉันคิดว่าการตัดสินใจของคุณไม่เป็นกลางและเป็นตัวแทนฉันเห็นคำตอบที่คล้ายกันมากมายในสแต็คและก็โอเคฉันจะใช้โซลูชันของฉันและอาจมีบางคนเลือกโซลูชันของฉันในอนาคต จุดลบเหล่านี้ทำให้ยากต่อการค้นหาสิ่งสำคัญที่สุดคือสิ่งที่ถูกต้องและไม่คัดลอก
Bronek

3
@Bronek ถ้าคุณไม่ ping ฉันฉันไม่ได้รับการบ่งชี้ว่าคุณตอบ ฉันไม่ได้ลบความคิดเห็นของคุณฉันไม่มีความสามารถหรือต้องการทำเช่นนั้น น่าจะเป็น mod มาโดยและลบมัน - คุณกำลังต้อนรับธงมันสำหรับความสนใจของผู้ดูแลและถามว่าทำไมหรือดีกว่ายัง - ถามในMeta กองมากเกิน ฉันมีความคิดเห็นเกี่ยวกับวิธีการแก้ปัญหาของคุณจากจุดยืนในการเขียนโปรแกรมซึ่งอยู่ในด้านขวาของฉัน - นี่คือสิ่งที่ความคิดเห็นสำหรับการเริ่มต้นด้วยไม่จำเป็นต้องเป็นส่วนตัว
Benjamin Gruenbaum

8

ใช้วิธีการขยายแทน:

public static class ExtensionMethods
{
    public static int IntValue(this Enum argEnum)
    {
        return Convert.ToInt32(argEnum);
    }
}

และการใช้งานนั้นสวยกว่าเล็กน้อย:

var intValue = Question.Role.IntValue();

7
public enum Suit : int
{
    Spades = 0,
    Hearts = 1,
    Clubs = 2,
    Diamonds = 3
}

Console.WriteLine((int)(Suit)Enum.Parse(typeof(Suit), "Clubs"));

// From int
Console.WriteLine((Suit)1);

// From a number you can also
Console.WriteLine((Suit)Enum.ToObject(typeof(Suit), 1));

if (typeof(Suit).IsEnumDefined("Spades"))
{
    var res = (int)(Suit)Enum.Parse(typeof(Suit), "Spades");
    Console.Out.WriteLine("{0}", res);
}

ชุดสูท - "10. (เกมไพ่) ชุดไพ่แต่ละใบที่แยกแยะด้วยสีและ / หรือตราสัญลักษณ์ที่เฉพาะเจาะจงเช่นโพดำ, หัวใจ, เพชรหรือคลับแบบดั้งเดิมของแองโกล, สเปนและฝรั่งเศสไพ่"
Peter Mortensen

คำอธิบายของโค้ดตัวอย่างจะเป็นไปตามลำดับ (โดยการแก้ไขคำตอบของคุณไม่ใช่ที่นี่ในความคิดเห็น)
Peter Mortensen

โดยทั่วไปจะถูกสงวนไว้สำหรับสถานะ unset / unkown ใน enums ผิดปกติในการกำหนดเช่นนั้น
Chad Grant

6

ใช้:

Question question = Question.Role;
int value = question.GetHashCode();

value == 2มันจะส่งผลในการ

นี่คือความจริงเฉพาะในกรณีที่เหมาะกับ enum intภายใน


1
นี่เป็นจริงเฉพาะเมื่อ enum พอดีภายในintหลักสูตรตามที่GetHashCodeส่งกลับจำนวนเต็ม
RB

5

เนื่องจาก enums สามารถประกาศได้ด้วยหลายประเภทดั้งเดิมวิธีการขยายทั่วไปในการเลือกประเภท enum ใด ๆ จึงมีประโยชน์

enum Box
{
    HEIGHT,
    WIDTH,
    DEPTH
}

public static void UseEnum()
{
    int height = Box.HEIGHT.GetEnumValue<int>();
    int width = Box.WIDTH.GetEnumValue<int>();
    int depth = Box.DEPTH.GetEnumValue<int>();
}

public static T GetEnumValue<T>(this object e) => (T)e;

4

ต่อไปนี้เป็นวิธีการขยาย

public static string ToEnumString<TEnum>(this int enumValue)
{
    var enumString = enumValue.ToString();
    if (Enum.IsDefined(typeof(TEnum), enumValue))
    {
        enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
    }
    return enumString;
}

4

แฮ็คที่ฉันชอบด้วยจำนวนที่มากหรือน้อย:

GetHashCode();

สำหรับ enum

public enum Test
{
    Min = Int32.MinValue,
    One = 1,
    Max = Int32.MaxValue,
}

นี้,

var values = Enum.GetValues(typeof(Test));

foreach (var val in values)
{
    Console.WriteLine(val.GetHashCode());
    Console.WriteLine(((int)val));
    Console.WriteLine(val);
}

เอาท์พุท

one
1
1
max
2147483647
2147483647
min
-2147483648
-2147483648

Disclaimer:

มันใช้งานไม่ได้สำหรับ enums ตามความยาว


3

ทางออกที่ง่ายที่สุดที่ฉันคิดได้คือการGet(int)ใช้วิธีการมากเกินไป:

[modifiers] Questions Get(Question q)
{
    return Get((int)q);
}

ซึ่ง[modifiers]โดยทั่วไปสามารถเช่นเดียวกับGet(int)วิธีการ หากคุณไม่สามารถแก้ไขQuestionsชั้นเรียนหรือด้วยเหตุผลบางอย่างที่ไม่ต้องการคุณสามารถใช้วิธีมากเกินไปโดยการเขียนส่วนขยาย:

public static class Extensions
{
    public static Questions Get(this Questions qs, Question q)
    {
        return qs.Get((int)q);
    }
}

3

ตัวอย่างที่ฉันอยากจะแนะนำ "เพื่อให้ได้ค่า 'int' จาก enum" คือ

public enum Sample
{
    Book = 1, 
    Pen = 2, 
    Pencil = 3
}

int answer = (int)Sample.Book;

ตอนนี้คำตอบจะเป็น 1



2

ลองอันนี้แทนที่จะเปลี่ยน enum เป็น int:

public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}


0

ฉันคิดวิธีส่วนขยายนี้ที่มีคุณสมบัติภาษาปัจจุบัน ด้วยการใช้ไดนามิกฉันไม่จำเป็นต้องทำให้วิธีนี้เป็นแบบทั่วไปและระบุชนิดที่ทำให้การเรียกใช้ง่ายขึ้นและสอดคล้องกัน:

public static class EnumEx
{
    public static dynamic Value(this Enum e)
    {
        switch (e.GetTypeCode())
        {
            case TypeCode.Byte:
            {
                return (byte) (IConvertible) e;
            }

            case TypeCode.Int16:
            {
                return (short) (IConvertible) e;
            }

            case TypeCode.Int32:
            {
                return (int) (IConvertible) e;
            }

            case TypeCode.Int64:
            {
                return (long) (IConvertible) e;
            }

            case TypeCode.UInt16:
            {
                return (ushort) (IConvertible) e;
            }

            case TypeCode.UInt32:
            {
                return (uint) (IConvertible) e;
            }

            case TypeCode.UInt64:
            {
                return (ulong) (IConvertible) e;
            }

            case TypeCode.SByte:
            {
                return (sbyte) (IConvertible) e;
            }
        }

        return 0;
    }

โปรดอย่าคุณสามารถทำสิ่งนี้ได้ในหนึ่งบรรทัด Convert.Changetype (e, e.GetTypeCode ()) และรับวัตถุกลับมาไม่จำเป็นต้องมีการเปลี่ยนแปลงหรือวิธีการขยาย
Chad Grant

ฉันจะไม่เห็นด้วยกับการใช้งานการแปลง เพียงแค่ใช้นักแสดงจะง่ายขึ้น ความตั้งใจของฉันคือสามารถแปลงค่า enum ให้เป็นค่าได้โดยไม่ต้องใช้นักแสดง สิ่งนี้ยอมให้การเปลี่ยนแปลงของ enum ประเภท wihtout ไม่จำเป็นต้องเปลี่ยน cast ที่เกี่ยวข้องทั้งหมด - แต่จะเกิดอะไรขึ้นเมื่อไหร่? วิธีการขยายทำงานอย่างถูกต้อง อย่างไรก็ตามฉันมีปัญหากับมันเนื่องจากมันเป็นแบบไดนามิก complier ไม่สามารถพิมพ์การตรวจสอบ (สำหรับคำสั่งทั้งหมดที่เห็นได้ชัด) ซึ่งหมายถึงการตรวจสอบชนิดเกิดขึ้นเมื่อทำงาน - ไม่ใช่ทางออกที่ดี ฉันคิดว่าฉันจะกลับไปปลดเปลื้อง
Jeff

1
ฉันไม่ได้บอกว่าใช้มันไปกับการร่ายรหัสนี้ไร้สาระและไม่ทำอะไรเลยจริง ๆ แล้วทำให้ปัญหาแย่ลง ฉันขอแนะนำให้ลบโซลูชันนี้
Chad Grant
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.