หลายกรณีในคำสั่งเปลี่ยน


582

มีวิธีการผ่านงบหลายกรณีโดยไม่ระบุcase value:ซ้ำ ๆ ?

ฉันรู้ว่างานนี้:

switch (value)
{
   case 1:
   case 2:
   case 3:
      // Do some stuff
      break;
   case 4:
   case 5:
   case 6:
      // Do some different stuff
      break;
   default:
       // Default stuff
      break;
}

แต่ฉันต้องการทำสิ่งนี้:

switch (value)
{
   case 1,2,3:
      // Do something
      break;
   case 4,5,6:
      // Do something
      break;
   default:
      // Do the Default
      break;
}

ไวยากรณ์นี้ฉันกำลังคิดถึงจากภาษาอื่นหรือฉันขาดอะไรไปหรือเปล่า?


มีเหตุผลที่คุณไม่เพียงแค่ใช้คำสั่ง IF (ถ้าคุณกำลังตรวจสอบช่วงของ ints)?
Eric Schoonover

2
ใช่ charlse วิธีแรกใช้งานได้ดีฉันใช้มันในหลาย ๆ ที่ มันสกปรกกว่าที่ฉันต้องการ แต่มันมีประโยชน์ ฉันแค่ใช้จำนวนเต็มเหล่านั้นเป็นตัวอย่าง ข้อมูลจริงมีความหลากหลายมากขึ้น ถ้า (1 || 2 || 3) {... } อื่นถ้า (4 || 5 || 6) {... } ก็ใช้ได้เหมือนกัน แต่ก็อ่านยากกว่า
theo

5
ทำไมคุณถึงคิดว่าสกปรกกว่าสมัยก่อน หลังเพิ่มความหมายอื่น,และหนึ่งที่ไม่ได้ใช้ร่วมกับภาษาสไตล์ c อื่น ๆ นั่นจะดูสกปรกกว่าสำหรับฉันมาก
Jon Hanna

1
คุณอาจเลือกไวยากรณ์ที่ 2 จาก Ruby นั่นเป็นวิธีการทำงานในภาษานั้น (แม้ว่าสวิตช์จะกลายเป็นตัวพิมพ์เล็กและตัวพิมพ์ใหญ่จะกลายเป็นช่วงเวลาเมื่อ
เทียบกับ

4
หมายเหตุสำคัญ รองรับช่วงในกรณีสวิตช์เริ่มต้น C # v7 - โปรดดูคำตอบ
RBT

คำตอบ:


313

ไม่มีไวยากรณ์ใน C ++ หรือ C # สำหรับวิธีที่สองที่คุณกล่าวถึง

ไม่มีอะไรผิดปกติกับวิธีแรกของคุณ หากคุณมีช่วงที่ใหญ่มากเพียงใช้ชุดคำสั่ง if


5
นอกจากนี้ในฐานะที่ผมอยากจะเพิ่มการเชื่อมโยงข้อมูลจำเพาะของภาษา C # ที่มีอยู่ใน MSDN ที่msdn.microsoft.com/en-us/vcsharp/aa336809.aspx
ริชาร์ดแมคไกวร์

ผู้ใช้สามารถใช้งาน if's (หรือการค้นหาตาราง) เพื่อลดอินพุตให้เป็นชุด enums และเปิด enum
Harvey

5
อาจเลือกจาก VB.net
George Birbilis

1
VB.net ดีกว่าสำหรับคำสั่งกรณีต่าง ๆ ... ยกเว้นพวกเขาจะไม่ผ่านเหมือนที่ C # ทำ ใช้เวลาเล็กน้อยให้เล็กน้อย
Brain2000

ฉันเชื่อว่านี่ไม่ถูกต้องอีกต่อไป ดูstackoverflow.com/questions/20147879/… . นอกจากนี้ในคำถามนี้มีคำตอบstackoverflow.com/a/44848705/1073157
Dan Rayson

700

ฉันเดาว่านี่ได้รับคำตอบแล้ว อย่างไรก็ตามฉันคิดว่าคุณยังสามารถผสมตัวเลือกทั้งสองในวิธีที่ดีขึ้นโดยการทำ syntactically:

switch (value)
{
    case 1: case 2: case 3:          
        // Do Something
        break;
    case 4: case 5: case 6: 
        // Do Something
        break;
    default:
        // Do Something
        break;
}

3
'switch' ควรเป็นตัวพิมพ์เล็กสำหรับ c # หรือไม่
Austin Harris

3
รหัสที่ถูกยุบจะยาวขึ้นเป็นตัวอย่างแรกในคำถาม อาจเช่นกันเพียงทำตามที่เป็นอยู่ในคำถาม
MetalPhoenix

10
ทำไมต้องรำคาญ ตัวกดอัตโนมัติใน Visual Studio 2013 จะเปลี่ยนกลับเป็นรูปแบบในคำถามเดิมต่อไป
กุสตาฟ

14
@T_D ได้รับการสนับสนุนเพราะจริง ๆ แล้วตอบคำถาม OP กล่าวว่าฉันทำอะไรหายไป ... Carlos ตอบพร้อมกับสิ่งที่เขาขาดไป ดูเหมือนว่าจะสวยและแห้งสำหรับฉัน อย่าเกลียดที่เขามีผู้โหวตขึ้น 422 คน
Mike Devenney

8
@MikeDevenney จากนั้นคุณตีความคำถามต่าง ๆ เท่าที่ฉันเห็นคำตอบที่ถูกต้องจะเป็น "ไม่ c # ไม่มีไวยากรณ์ใด ๆ สำหรับเรื่องนั้น" หากมีคนถามว่า "เป็นไปได้หรือไม่ที่จะเทของเหลวลงในแก้วที่ฉันถือคว่ำ?" คำตอบควรเป็น "ไม่" และไม่ใช่ "คุณสามารถเทของเหลวลงไปหากคุณมองมันกลับหัวและใช้จินตนาการของคุณ" เพราะคำตอบนี้เป็นเรื่องเกี่ยวกับการใช้จินตนาการ หากคุณใช้ไวยากรณ์ปกติ แต่การจัดรูปแบบมันไม่ดีมันดูเหมือนไวยากรณ์อื่น ๆ ที่มีจินตนาการ หวังว่าคุณจะได้คะแนนของฉัน ... : P
T_D

74

รูปแบบนี้อยู่ห่างจาก Visual Basic เลือก ... กรณีคำชี้แจง :

Dim number As Integer = 8
Select Case number
    Case 1 To 5
        Debug.WriteLine("Between 1 and 5, inclusive")
        ' The following is the only Case clause that evaluates to True.
    Case 6, 7, 8
        Debug.WriteLine("Between 6 and 8, inclusive")
    Case Is < 1
        Debug.WriteLine("Equal to 9 or 10")
    Case Else
        Debug.WriteLine("Not between 1 and 10, inclusive")
End Select

คุณไม่สามารถใช้ไวยากรณ์นี้ใน C # คุณต้องใช้ไวยากรณ์จากตัวอย่างแรกของคุณแทน


49
นี่เป็นหนึ่งในบางสิ่งที่ฉันคิดถึง * พื้นฐาน
nickf

10
ที่นี่เรามีหนึ่งในไม่กี่หน้าจอที่ Visual Basic ไม่น่าเกลียดและมีความหลากหลายมากกว่า c # นี่เป็นตัวอย่างที่มีค่า!
bgmCoder

อันนี้ค่อนข้างดี ฉันสงสัยว่าทำไมสิ่งนี้จึงไม่ถูกเพิ่มใน C # 8.0 จะสวยดี
Sigex

69

ใน C # 7 (พร้อมใช้งานโดยค่าเริ่มต้นใน Visual Studio 2017 / .NET Framework 4.6.2) การสลับตามช่วงเวลาเป็นไปได้ด้วยคำสั่งสวิตช์และจะช่วยแก้ไขปัญหาของ OP

ตัวอย่าง:

int i = 5;

switch (i)
{
    case int n when (n >= 7):
        Console.WriteLine($"I am 7 or above: {n}");
        break;

    case int n when (n >= 4 && n <= 6 ):
        Console.WriteLine($"I am between 4 and 6: {n}");
        break;

    case int n when (n <= 3):
        Console.WriteLine($"I am 3 or less: {n}");
        break;
}

// Output: I am between 4 and 6: 5

หมายเหตุ:

  • วงเล็บ(และ)ไม่จำเป็นในwhenเงื่อนไข แต่ใช้ในตัวอย่างนี้เพื่อเน้นการเปรียบเทียบ
  • varintนอกจากนี้ยังอาจถูกนำมาใช้แทน ตัวอย่างเช่นcase var n when n >= 7:.

3
(การจับคู่รูปแบบ) โดยทั่วไปควรเป็นแนวปฏิบัติที่ดีที่สุดเมื่อคุณสามารถใช้ C # 7.x หรือสูงกว่าเนื่องจากมีความชัดเจนมากกว่าคำตอบอื่น ๆ
UndyingJellyfish

มีวิธีในการบรรลุสิ่งนี้ด้วยรายการ Enums หรือไม่? ที่ Enums แผนที่เพื่อ int?
Sigex


20

.NET Framework 3.5 มีช่วง:

Enumerable.Range จาก MSDN

คุณสามารถใช้มันกับ "มี" และคำสั่ง IF เพราะเหมือนมีคนพูดว่าคำสั่งสวิทช์ใช้ตัวดำเนินการ "=="

นี่คือตัวอย่าง:

int c = 2;
if(Enumerable.Range(0,10).Contains(c))
    DoThing();
else if(Enumerable.Range(11,20).Contains(c))
    DoAnotherThing();

แต่ฉันคิดว่าเราสนุกได้มากกว่านี้: เนื่องจากคุณไม่ต้องการค่าตอบแทนและการกระทำนี้ไม่ใช้พารามิเตอร์คุณสามารถใช้การกระทำได้อย่างง่ายดาย!

public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
    if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
        action();
}

ตัวอย่างเก่าด้วยวิธีการใหม่นี้:

MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);

เมื่อคุณผ่านการกระทำไม่ใช่คุณค่าคุณควรละเว้นวงเล็บมันสำคัญมาก หากคุณต้องการฟังก์ชั่นที่มีการขัดแย้งเพียงแค่เปลี่ยนประเภทของการAction หากคุณจำเป็นต้องคืนค่าใช้Action<ParameterType>Func<ParameterType, ReturnType>

ใน C # 3.0 ไม่มีแอพพลิเคชั่นบางส่วนที่ง่ายในการแค็ปซูลข้อเท็จจริงพารามิเตอร์ case เหมือนกัน แต่คุณสร้างเมธอดตัวช่วยเล็กน้อย (bit verbose, tho)

public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){ 
    MySwitchWithEnumerable(3, startNumber, endNumber, action); 
}

นี่คือตัวอย่างของคำสั่งที่นำเข้าฟังก์ชั่นใหม่ที่ IMHO ทรงพลังและสง่างามกว่าคำสั่งเก่า ๆ


3
ทางเลือกที่ดี. สิ่งหนึ่งที่จะต้องทราบแม้ว่า - Enumerable.Range มีข้อโต้แย้งและint start int countตัวอย่างของคุณไม่ถูกต้องตามวิธีที่เขียน int endคุณเขียนมันราวกับว่าอาร์กิวเมนต์ที่สองคือ ตัวอย่างเช่น - Enumerable.Range(11,20)จะส่งผลให้มี 20 หมายเลขที่ขึ้นต้นด้วย 11 และไม่ใช่ตัวเลขตั้งแต่ 11 ถึง 20
Gabriel McAdams

แม้ว่าถ้าทำงานกับ Enum ทำไมไม่เหมือนกัน if (Enumerable.Range (MyEnum.A, MyEnum.M) {DoThing ();} อื่นถ้า (Enumerable.Range (MyEnum.N, MyEnum.Z) {DoAnotherThing ();}
David Hollowell

4
โปรดทราบว่า Enumerable.Range(11,20).Contains(c)เทียบเท่ากับfor(int i = 11; i < 21; ++i){ if (i == c) return true; } return false;หากคุณมีช่วงกว้างมันจะใช้เวลานานในขณะที่เพิ่งใช้>และ<จะรวดเร็วและคงที่
Jon Hanna

การปรับปรุง: การมีMySwitchWithEnumerableผลตอบแทนvoidคือการออกแบบที่อ่อนแอสำหรับสถานการณ์นี้ เหตุผล: คุณได้เปลี่ยนif-elseเป็นชุดของข้อความอิสระ - ซึ่งซ่อนเจตนาซึ่งก็คือพวกเขาเป็นเอกสิทธิ์เฉพาะบุคคล - actionดำเนินการเพียงคนเดียว แต่กลับboolมีร่างกายเว็บไซต์โทรแล้วแสดงให้เห็นถึงความตั้งใจที่:if (..) { action(); return true; } else return false; if (MySwitchWithEnumerable(..)) else (MySwitchWithEnumerable(..));นี้เป็นที่นิยมกว่า อย่างไรก็ตามมันไม่ได้เป็นการปรับปรุงอย่างมีนัยสำคัญจากเวอร์ชั่นดั้งเดิมของคุณอีกต่อไปสำหรับกรณีแบบง่าย ๆ นี้
ToolmakerSteve

15

นี่คือโซลูชัน C # 7 ที่สมบูรณ์ ...

switch (value)
{
   case var s when new[] { 1,2,3 }.Contains(s):
      // Do something
      break;
   case var s when new[] { 4,5,6 }.Contains(s):
      // Do something
      break;
   default:
      // Do the default
      break;
}

มันใช้งานได้กับสตริงด้วย ...

switch (mystring)
{
   case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
      // Do something
      break;
...
}

นี่หมายความว่าคุณจัดสรรอาร์เรย์ด้วยคำสั่ง switch แต่ละอันใช่มั้ย จะดีกว่าไหมถ้าเราให้พวกมันเป็นตัวแปรคงที่?
MaLiN2223

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

11

รหัสด้านล่างใช้ไม่ได้ :

case 1 | 3 | 5:
// Not working do something

วิธีเดียวที่จะทำสิ่งนี้คือ:

case 1: case 2: case 3:
// Do something
break;

รหัสที่คุณกำลังมองหางานใน Visual Basic ที่คุณสามารถใส่ช่วง ... ในnoneตัวเลือกของswitchคำสั่งหรือif elseบล็อกที่สะดวกฉันขอแนะนำ ณ จุดที่สูงมากให้. dll กับ Visual Basic และนำกลับมา ในโครงการ C # ของคุณ

หมายเหตุ: เทียบเท่าสวิทช์ใน Visual Basic Select Caseเป็น


7

ตัวเลือกอื่นจะใช้ประจำ ถ้ากรณี 1-3 ทั้งหมดดำเนินการตรรกะเดียวกันให้ตัดตรรกะนั้นในรูทีนและเรียกมันสำหรับแต่ละกรณี ฉันรู้ว่านี่ไม่ได้กำจัดข้อความสั่งจริง แต่ใช้รูปแบบที่ดีและบำรุงรักษาให้น้อยที่สุด .....

[แก้ไข] เพิ่มการใช้งานทางเลือกเพื่อให้ตรงกับคำถามต้นฉบับ ... [/ แก้ไข]

switch (x)
{
   case 1:
      DoSomething();
      break;
   case 2:
      DoSomething();
      break;
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}

Alt

switch (x)
{
   case 1:
   case 2:
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}

5

ด้านหนึ่งของสวิตช์ที่รู้จักน้อยกว่าใน C # ก็คือมันต้องอาศัยโอเปอเรเตอร์ =และเนื่องจากมันสามารถอยู่เหนือคุณจึงอาจมีบางสิ่งเช่นนี้:


string s = foo();

switch (s) {
  case "abc": /*...*/ break;
  case "def": /*...*/ break;
}

4
นี่อาจกลายเป็น gotcha ที่ยิ่งใหญ่ในภายหลังสำหรับคนอื่นที่พยายามอ่านโค้ด
Andrew Harry

5

gcc ใช้ส่วนขยายในภาษา C เพื่อรองรับช่วงต่อเนื่อง:

switch (value)
{
   case 1...3:
      //Do Something
      break;
   case 4...6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

แก้ไข : เพิ่งสังเกตเห็นแท็ก C # ในคำถามดังนั้นคำตอบ gcc อาจไม่ช่วยได้


4

ใน C # 7 ตอนนี้เรามีการจับคู่รูปแบบเพื่อให้คุณสามารถทำสิ่งต่อไปนี้:

switch (age)
{
  case 50:
    ageBlock = "the big five-oh";
    break;
  case var testAge when (new List<int>()
      { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }).Contains(testAge):
    ageBlock = "octogenarian";
    break;
  case var testAge when ((testAge >= 90) & (testAge <= 99)):
    ageBlock = "nonagenarian";
    break;
  case var testAge when (testAge >= 100):
    ageBlock = "centenarian";
    break;
  default:
    ageBlock = "just old";
    break;
}

3

จริงๆแล้วฉันไม่ชอบคำสั่ง GOTO เหมือนกัน แต่มันเป็นวัสดุของ Microsoft อย่างเป็นทางการและนี่คือไวยากรณ์ที่ได้รับอนุญาตทั้งหมด

หากจุดสิ้นสุดของรายการคำสั่งของส่วนสวิตช์สามารถเข้าถึงได้เกิดข้อผิดพลาดในการคอมไพล์เวลา สิ่งนี้เรียกว่ากฎ "ไม่ตกลง" ตัวอย่าง

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
default:
   CaseOthers();
   break;
}

ถูกต้องเนื่องจากไม่มีส่วนสวิตช์มีจุดสิ้นสุดที่สามารถเข้าถึงได้ ไม่เหมือนกับ C และ C ++ การดำเนินการของส่วนสวิตช์ไม่ได้รับอนุญาตให้ "ตกหล่น" ไปยังส่วนสวิตช์ถัดไปและตัวอย่าง

switch (i) {
case 0:
   CaseZero();
case 1:
   CaseZeroOrOne();
default:
   CaseAny();
}

ส่งผลให้เกิดข้อผิดพลาดในการรวบรวมเวลา เมื่อเรียกใช้งานส่วนสวิตช์ตามด้วยการเรียกใช้ส่วนสวิตช์อื่นต้องใช้เคส goto หรือประโยคเริ่มต้น goto ที่ชัดเจน:

switch (i) {
case 0:
   CaseZero();
   goto case 1;
case 1:
   CaseZeroOrOne();
   goto default;
default:
   CaseAny();
   break;
}

อนุญาตให้ใช้ป้ายกำกับหลายป้ายในส่วนสวิตช์ ตัวอย่าง

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
case 2:
default:
   CaseTwo();
   break;
}

ฉันเชื่อว่าในกรณีพิเศษนี้สามารถใช้ GOTO ได้และเป็นวิธีเดียวที่จะโกง

ที่มา: http://msdn.microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx


โปรดทราบว่าในทางปฏิบัติgotoสามารถหลีกเลี่ยงได้เกือบทุกครั้ง (แม้ว่าฉันจะไม่คิดว่ามัน "แย่มาก" ที่นี่ - มันกำลังเติมบทบาทที่มีโครงสร้างเฉพาะเจาะจง) ในตัวอย่างของคุณเพราะคุณได้ห่อศพในกรณีที่ฟังก์ชั่น (เป็นสิ่งที่ดี) กรณี 0 CaseZero(); CaseZeroOrOne(); break;จะกลายเป็น ไม่gotoจำเป็น
ToolmakerSteve

ลิงค์เสียครึ่ง (เปลี่ยนเส้นทาง, "Visual Studio 2003 Retired Technical Document" )
Peter Mortensen

2

ดูเหมือนว่าจะมีงานที่น่าสะพรึงกลัวมากมายในการหาวิธีที่จะใช้หนึ่งใน C # ที่ใช้ไวยากรณ์น้อยที่สุดเพื่อให้ดูดีขึ้นหรือทำงานได้ดีขึ้น โดยส่วนตัวฉันพบว่าคำสั่ง switch นั้นไม่ค่อยคุ้มค่าที่จะใช้ ฉันขอแนะนำอย่างยิ่งให้วิเคราะห์ข้อมูลที่คุณกำลังทดสอบและผลลัพธ์สุดท้ายที่คุณต้องการ

ให้เราพูดเช่นคุณต้องการทดสอบค่าอย่างรวดเร็วในช่วงที่ทราบเพื่อดูว่าเป็นจำนวนเฉพาะหรือไม่ คุณต้องการหลีกเลี่ยงการใช้รหัสของคุณทำการคำนวณที่สิ้นเปลืองและคุณสามารถค้นหารายการของจำนวนเฉพาะในช่วงที่คุณต้องการออนไลน์ คุณสามารถใช้คำสั่ง switch ขนาดใหญ่เพื่อเปรียบเทียบแต่ละค่ากับจำนวนเฉพาะที่ทราบ

หรือคุณเพียงแค่สร้างแผนที่อาร์เรย์ของช่วงเวลาและรับผลทันที:

    bool[] Primes = new bool[] {
        false, false, true, true, false, true, false,    
        true, false, false, false, true, false, true,
        false,false,false,true,false,true,false};
    private void button1_Click(object sender, EventArgs e) {
        int Value = Convert.ToInt32(textBox1.Text);
        if ((Value >= 0) && (Value < Primes.Length)) {
            bool IsPrime = Primes[Value];
            textBox2.Text = IsPrime.ToString();
        }
    }

บางทีคุณอาจต้องการดูว่าอักขระในสตริงนั้นเป็นเลขฐานสิบหกหรือไม่ คุณสามารถใช้คำสั่ง switch ที่ไม่ใหญ่และค่อนข้างใหญ่

หรือคุณสามารถใช้นิพจน์ทั่วไปเพื่อทดสอบ char หรือใช้ฟังก์ชัน IndexOf เพื่อค้นหาอักขระ char ในสตริงของตัวอักษรฐานสิบหกที่รู้จักกัน:

        private void textBox2_TextChanged(object sender, EventArgs e) {
        try {
            textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToString();
        } catch {
        }
    }

ให้เราบอกว่าคุณต้องการทำหนึ่งใน 3 การกระทำที่แตกต่างกันขึ้นอยู่กับค่าที่จะอยู่ในช่วง 1 ถึง 24 ฉันขอแนะนำให้ใช้ชุดคำสั่ง IF และถ้ามันซับซ้อนเกินไป (หรือจำนวนที่มากขึ้นเช่น 5 การกระทำที่แตกต่างกันขึ้นอยู่กับค่าในช่วง 1 ถึง 90) จากนั้นใช้ enum เพื่อกำหนดการกระทำและสร้างแผนที่อาร์เรย์ของ enums จากนั้นค่าจะถูกใช้เพื่อทำดัชนีลงในแผนผังอาร์เรย์และรับ enum ของการกระทำที่คุณต้องการ จากนั้นใช้ชุดคำสั่ง IF ขนาดเล็กหรือชุดคำสั่งสวิตช์อย่างง่าย ๆ เพื่อประมวลผลค่า enum ที่เกิดขึ้น

นอกจากนี้สิ่งที่ดีเกี่ยวกับแผนที่อาเรย์ที่แปลงช่วงของค่าเป็นการกระทำคือมันสามารถเปลี่ยนได้ง่าย ๆ โดยรหัส ด้วยโค้ดแบบใช้สายยากคุณจะไม่สามารถเปลี่ยนพฤติกรรมที่รันไทม์ได้อย่างง่ายดาย แต่ด้วยแผนที่อาเรย์จึงเป็นเรื่องง่าย


คุณสามารถแมปแลมบ์ดาหรือตัวแทน
Conrad Frix

จุดที่ดี หนึ่งความคิดเห็นเล็กน้อย: ฉันมักจะพบว่าง่ายต่อการรักษารายการของค่าที่ตรงกับกรณีที่กำหนดกว่าแผนที่อาเรย์ ปัญหาของแผนที่อาเรย์คือการทำผิดพลาดง่าย ตัวอย่างเช่นแทนที่จะใช้แผนผังอาเรย์ช่วงเวลาเฉพาะของจริง / เท็จเพียงแค่มีรายการช่วงเวลาและโหลดลงใน HashSet เพื่อประสิทธิภาพการค้นหา แม้ว่าจะมีมากกว่าสองกรณีโดยปกติแล้วทั้งหมดเป็นหนึ่งกรณีเป็นรายการเล็ก ๆ ดังนั้นให้สร้าง HashSet of enums (ถ้ากระจัดกระจาย) หรืออาเรย์แผนที่ในรหัสจากรายการของอีกกรณีหนึ่ง
ToolmakerSteve

1

เพียงเพิ่มการสนทนาโดยใช้. NET 4.6.2 ฉันยังสามารถทำต่อไปนี้ ฉันทดสอบโค้ดแล้วและได้ผลกับฉัน

คุณยังสามารถทำคำสั่ง "หรือ" หลายรายการเช่นด้านล่าง:

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when b.Contains("text3") || b.Contains("text4") || b.Contains("text5"):
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }

นอกจากนี้คุณยังสามารถตรวจสอบว่ามันตรงกับค่าในอาร์เรย์:

            string[] statuses = { "text3", "text4", "text5"};

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when statuses.Contains(value):                        
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }

สิ่งนี้ไม่ได้ขึ้นอยู่กับรุ่น C # ไม่ใช่รุ่น NET หรือไม่
Peter Mortensen

1

หากคุณมีจำนวนมากของสตริง (หรือประเภทอื่น ๆ ) กรณีทั้งหมดทำในสิ่งเดียวกันฉันขอแนะนำให้ใช้รายการสตริงรวมกับคุณสมบัติ string.Contains

ดังนั้นหากคุณมีคำสั่ง switch ขนาดใหญ่เช่นนี้:

switch (stringValue)
{
    case "cat":
    case "dog":
    case "string3":
    ...
    case "+1000 more string": // Too many string to write a case for all!
        // Do something;
    case "a lonely case"
        // Do something else;
    .
    .
    .
}

คุณอาจต้องการแทนที่ด้วยifคำสั่งเช่นนี้:

// Define all the similar "case" string in a List
List<string> listString = new List<string>(){ "cat", "dog", "string3", "+1000 more string"};
// Use string.Contains to find what you are looking for
if (listString.Contains(stringValue))
{
    // Do something;
}
else
{
    // Then go back to a switch statement inside the else for the remaining cases if you really need to
}

ขนาดนี้เหมาะสำหรับกรณีสตริงจำนวนเท่าใดก็ได้


0

ฉันคิดว่าอันนี้ดีกว่าใน C # 7 หรือสูงกว่า

switch (value)
{
    case var s when new[] { 1,2 }.Contains(s):
    // Do something
     break;

    default:
    // Do the default
    break;
 }

นอกจากนี้คุณยังสามารถตรวจสอบช่วงในกรณีสวิตช์ C #: กรณีเปลี่ยน: ฉันสามารถใช้ช่วงแทนหนึ่งตัวเลข หรือถ้าคุณต้องการที่จะเข้าใจพื้นฐานของ กรณีเปลี่ยน C #


-5

สำหรับสิ่งนี้คุณจะใช้คำสั่ง goto เช่น:

    switch(value){
    case 1:
        goto case 3;
    case 2:
        goto case 3;
    case 3:
        DoCase123();
    //This would work too, but I'm not sure if it's slower
    case 4:
        goto case 5;
    case 5:
        goto case 6;
    case 6:
        goto case 7;
    case 7:
        DoCase4567();
    }

7
@scone goto ทำลายหลักการพื้นฐานของการโปรแกรมขั้นตอน (ซึ่ง c ++ และ c # ยังคงถูกฝังอยู่ในนั้นพวกเขาไม่ใช่ภาษา OO บริสุทธิ์ (ขอบคุณพระเจ้า) การโปรแกรมเชิงโพรซีเดอร์นั้นมีลอจิกที่กำหนดไว้อย่างดีซึ่งกำหนดโดยการสร้างภาษาและระเบียบวิธีการเรียกใช้เมธอด (การเพิ่มและลดขนาดของ runtime runtime) คำสั่ง goto หลีกเลี่ยงการไหลนี้โดยอนุญาตให้กระโดดไปรอบ ๆ โดยพลการ
samis

1
ฉันไม่ได้บอกว่ามันเป็นสไตล์ที่ดีพูดคุย แต่ก็ทำในสิ่งที่คำถามเดิมถาม
สโคน

2
ไม่มันไม่ "ทำในสิ่งที่เป็นต้นฉบับของคำถาม" คำถามเดิมมีรหัสที่ทำงานตามที่เป็นอยู่ พวกเขาไม่ต้องการแก้ไข และแม้ว่าพวกเขาจะทำนี่เป็นข้อเสนอแนะที่น่ากลัว มันน้อยgotoรัดกุมและการใช้งาน ยิ่งไปกว่านั้นมันเป็นการใช้ที่ไม่จำเป็นโดยสิ้นเชิงgotoเนื่องจากไวยากรณ์ดั้งเดิมที่ OP ระบุไว้ใช้งานได้ คำถามคือว่ามีวิธีรัดกุมมากขึ้นเพื่อให้กรณีอื่น อย่างที่ผู้คนเคยตอบเมื่อหลายปีก่อนคุณเคยมีใช่ - ถ้าคุณเต็มใจที่จะใส่หลาย ๆ กรณีในหนึ่งบรรทัดcase 1: case 2:และหากสไตล์อัตโนมัติของโปรแกรมแก้ไขอนุญาต
ToolmakerSteve

เหตุผลเดียวที่ goto ตั้งใจแน่วแน่ว่าไม่ดีเพราะบางคนคิดว่ามันยากที่จะทำตามการไหลของตรรกะ . Net MSIL (รหัสวัตถุรวมตัว) ใช้ goto ไปทั่วเพราะมันรวดเร็ว แต่ถ้า. code สุทธิสามารถเขียนได้และเหมือนกับนักแสดงที่ไม่มีพวกเขามันจะดีกว่าถ้าคุณไม่ใช้มันดังนั้นคุณจะไม่โดนคนอื่นเช่น @ ToolmakerSteve คำตอบที่น่ายกย่อง
dynamiclynk

@wchoward - โปรดอ่านคำตอบของฉันเพิ่มเติมอย่างระมัดระวัง การร้องเรียนของฉันคือไม่เพียงเกี่ยวกับการใช้งานของโกโตะ ฉันคัดค้านเพราะคำถามแสดงรหัสที่ใช้งานได้แล้วและคำตอบนี้) ใช้รหัสนั้นและทำให้ละเอียดมากขึ้นและมีโครงสร้างน้อยกว่าไม่มีประโยชน์ b) ไม่ตอบคำถาม
ToolmakerSteve
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.