ที่ประกอบไปด้วยหรือไม่ที่จะไม่ประกอบไปด้วย? [ปิด]


186

ฉันเป็นผู้ให้การสนับสนุนผู้ประกอบการที่ประกอบไปด้วยส่วนตัว: ()? :; ฉันรู้ว่ามันมีที่อยู่ แต่ฉันได้เจอโปรแกรมเมอร์หลายคนที่ไม่เคยใช้งานมาก่อนและบางคนก็ใช้มันบ่อยเกินไป

คุณรู้สึกยังไงกับเรื่องนี้? คุณเห็นโค้ดที่น่าสนใจอะไรที่ใช้มัน?


22
ผู้สนับสนุนบางสิ่งบางอย่างคือคนที่สนับสนุนสิ่งนั้น
Doug McClean

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

3
จริงๆแล้วมันเป็นผู้ดำเนินการตามเงื่อนไข สนิทไปซ้ำคำถามstackoverflow.com/questions/725973/...
Daniel Daranas

บางครั้งผมใช้x = x if x else yแต่แล้วถามเกี่ยวกับเรื่องนี้และตระหนักถึงความช่วยเหลือกับคนอื่น ๆ ว่ามันจริงๆเพียงแค่ลด x = x หรือ Y ( stackoverflow.com/questions/18199381/self-referencing-ternary/... )
ยู่ยี่

4
คำถามเช่นนี้ไม่ควรได้รับการพิจารณาว่าไม่สร้างสรรค์
Ungeheuer

คำตอบ:


243

ใช้สำหรับการแสดงออกอย่างง่ายเท่านั้น :

int a = (b > 10) ? c : d;

อย่าโยงหรือทำเครื่องหมายผู้ประกอบการที่สามเนื่องจากยากต่อการอ่านและสับสน:

int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8;

ยิ่งไปกว่านั้นเมื่อใช้ตัวดำเนินการแบบไตรภาคพิจารณาการจัดรูปแบบรหัสในวิธีที่ปรับปรุงความสามารถในการอ่าน:

int a = (b > 10) ? some_value                 
                 : another_value;

81
เห็นด้วยอย่างยิ่งกับข้อความสองสามข้อแรก แต่ไม่เห็นด้วยกับตัวอย่างของ "ความสามารถในการอ่านที่ดีขึ้น" โดยสิ้นเชิง หากคุณกำลังจะไปหลายบรรทัดทำไมไม่ใช้เพียงคำสั่ง if?
Joe Phillips

3
เพียงเพราะถ้าอื่นเป็น verbose ค่อนข้างมากสำหรับการตัดสินใจง่าย: int a = 0; ถ้า (b> 10) a = some_value; อื่น a = another_value; คุณชอบอะไร
marcospereira

44
@ d03boy: เพราะถ้าคำสั่งเป็นเพียงแค่คำสั่งและจะไม่ทำเมื่อทุกสิ่งที่คุณต้องการคือการแสดงออก
falstro

2
@roe ในบางภาษาหากเป็นการแสดงออก (เช่นใน Scala) ดังนั้นจึงval x = if(true) 0 else 1ถูกกฎหมายอย่างสมบูรณ์
om-nom-nom

5
@ om-nom-nom case ในจุดที่จะทำให้เป็น if-expression แทนที่จะเป็น if-statement และโดยพื้นฐานแล้วเป็นสิ่งเดียวกันกับตัวดำเนินการ?: -
falstro

141

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


44
นั่นเป็นข้อโต้แย้งที่ดีที่สุดสำหรับผู้ประกอบการที่ฉันเคยได้ยินมา ฉันไม่ซื้ออาร์กิวเมนต์ "ไม่สามารถอ่านได้" (ฟังดูเหมือนว่าฉันเป็นคนขี้เกียจเกินกว่าจะชินกับมัน) แต่อันที่จริงแล้วมันมีเนื้อหา
EpsilonVector

80

ฉันรักพวกเขาโดยเฉพาะอย่างยิ่งในภาษาที่ปลอดภัยประเภท

ฉันไม่เห็นสิ่งนี้:

int count = (condition) ? 1 : 0;

ยากกว่านี้ไหม:

int count;

if (condition)
{
  count = 1;
} 
else
{
  count = 0;
}

แก้ไข -

ฉันขอยืนยันว่าผู้ประกอบการที่ประกอบไปด้วยไตรภาคทำให้ทุกอย่างซับซ้อนน้อยลงและประณีตกว่าทางเลือกอื่น


5
การเริ่มต้น Ternary มีประโยชน์มากขึ้นใน D หรือ C ++ เมื่อตัวแปรคงที่ เช่น const int count = ...;
deft_code

คุณเป็นคนที่เข้าใจผิด if/elseกับเครื่องมือจัดฟันที่ไม่จำเป็น
bobobobo

1
นอกจากนี้ในกรณีนี้ถ้าconditionเป็นbool คุณก็สามารถทำ int count = condition;
bobobobo

1
@bobobobo นี้if/elseมีเครื่องหมายวงเล็บเป็นวิธีที่โปรแกรมเมอร์ส่วนใหญ่จะเขียน ternary ..
Andre Figueiredo

1
@bobobobo หาก / ไม่มีวงเล็บปีกกากำลังขอปัญหา มันง่ายเกินไปที่คนจะเพิ่มบรรทัด แต่ลืมไปว่าต้องใช้เครื่องมือจัดฟันเพื่อทำสิ่งที่พวกเขาคาดหวัง (รันบรรทัดเพิ่มเติมที่เป็นส่วนหนึ่งของบล็อก): stackoverflow.com/a/381274/377225
George Marian

43

ถูกล่ามโซ่ฉันสบายดีด้วย - ซ้อนกันไม่มาก

ฉันมักจะใช้พวกเขามากขึ้นใน C เพียงแค่ b / c พวกเขาเป็นคำสั่ง if ที่มีค่าดังนั้นจึงลดการทำซ้ำหรือตัวแปรที่ไม่จำเป็น:

x = (y < 100) ? "dog" :
    (y < 150) ? "cat" :
    (y < 300) ? "bar" : "baz";

ค่อนข้างมากกว่า

     if (y < 100) { x = "dog"; } 
else if (y < 150) { x = "cat"; }
else if (y < 300) { x = "bar"; } 
else              { x = "baz"; }

ในการมอบหมายเช่นนี้ฉันพบว่ามันน้อยไปกว่า refactor และชัดเจนขึ้น

เมื่อฉันทำงานในทับทิมในอีกฉันมีแนวโน้มที่จะใช้if...else...endเพราะมันแสดงออกเช่นกัน

x =   if (y < 100) then "dog"
    elif (y < 150) then "cat"
    elif (y < 300) then "bar"
    else                "baz"
    end

(แม้ว่าเป็นที่ยอมรับสำหรับบางสิ่งบางอย่างที่เรียบง่ายแบบนี้ฉันอาจใช้ผู้ประกอบการที่สามแล้ว)


2
ฉันชอบตัวอย่างแรกของคุณ - ฉันไม่เคยคิดที่จะผูกมัดพวกเขาเช่นนั้นมาก่อน ขอบคุณสำหรับการแบ่งปัน. =)
Erik Forbes

5
+1 จริง ๆ แล้วฉันเพิ่งเริ่มทำสิ่งนั้น ที่จริงฉันยังทำแทนคำสั่งเปลี่ยน
Davy8

1
ตัวอย่างที่ยอดเยี่ยม @rampion
ylluminate

39

?:ผู้ประกอบการTernary เป็นเพียงการทำงานเทียบเท่าของขั้นตอนifสร้าง ดังนั้นตราบใดที่คุณไม่ได้ใช้?:นิพจน์ที่ซ้อนกันข้อโต้แย้งสำหรับ / กับการเป็นตัวแทนการทำงานของการดำเนินการใด ๆ ที่ใช้ที่นี่ แต่การดำเนินการแบบไตรภาคอาจส่งผลให้เกิดโค้ดที่ทำให้เกิดความสับสนอย่างร้ายแรง (การออกกำลังกายสำหรับผู้อ่าน: ลองเขียนโปรแกรมแยกวิเคราะห์ที่จะจัดการกับเงื่อนไขแบบไตรภาคที่ซ้อนกันและคุณจะเข้าใจความซับซ้อนของมัน)

แต่มีสถานการณ์มากมายที่การใช้งานตัว?:ดำเนินการอย่างระมัดระวังอาจส่งผลให้เกิดโค้ดที่อ่านง่ายกว่าจริง ๆ ตัวอย่างเช่น:

int compareTo(Object object) {
    if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) {
       return 1;
    if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) {
       return -1;
    else
      return 0;              
}

เปรียบเทียบกับสิ่งนี้:

int compareTo(Object object) {
    if(isLessThan(object))
        return reverseOrder ? 1 : -1;         
    else(isGreaterThan(object))
        return reverseOrder ? -1 : 1;
    else        
       return 0;              
}

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


ฉันจะยังคงสนับสนุนการใช้รางวัลในทุก ๆ การก่อสร้างถ้า / แล้ว / อื่นที่ไม่ใช่ส่วนที่สามดังนั้นตัวอย่างที่สองของคุณจะหายไปไม่กี่ imho
Kris

ใช่มันใช้งานได้ มันก็เหมือนกับการฟังก์ชั่นขนาดเล็กที่มีการโต้แย้งแบบบูเดียวและผลตอบแทนใด ๆประเภทที่คุณต้องการ! จริง ๆ แล้วผู้ดำเนินการเรียบร้อย
bobobobo

24

มันเป็นคำถามของสไตล์จริงๆ กฎของจิตใต้สำนึกที่ฉันมักจะปฏิบัติตามคือ:

  • ประเมินเพียง 1 นิพจน์เท่านั้นดังนั้นfoo = (bar > baz) ? true : falseไม่ใช่foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
  • ถ้าฉันใช้มันสำหรับตรรกะการแสดงผลเช่น <%= (foo) ? "Yes" : "No" %>
  • ใช้เพื่อการมอบหมายเท่านั้นจริงๆ; ไม่เคยไหลตรรกะ (ดังนั้นไม่เคย(foo) ? FooIsTrue(foo) : FooIsALie(foo)) ตรรกะการไหลในยุคที่สามเป็นเรื่องโกหกไม่สนใจจุดสุดท้าย

ฉันชอบเพราะมันกระชับและสง่างามสำหรับการดำเนินการมอบหมายอย่างง่าย


แนวทางที่ดีและตัวอย่างที่ดี!
nickf

ฉันคิดว่า langauges ส่วนใหญ่จะไม่ยอมให้คุณใช้กับตรรกะการไหลดังนั้นคุณจึงไม่สามารถทำ (foo) ได้จริง (foo): เท็จ (foo); นอกเสียจากว่าจะเป็นงานที่มอบหมาย
Henry B

อ๊ะใช่คุณพูดถูก
Keith Williams

21
สองตัวอย่างแรกของคุณแย่มาก ผลลัพธ์ของการเปรียบเทียบเป็นค่าบูลีนอยู่แล้วดังนั้นผู้ประกอบการที่ประกอบไปด้วยไตรภาคของคุณจึงไร้ประโยชน์และทำให้โค้ดซับซ้อนเท่านั้น
Trillian

1
@Trillian +1 ใช่ควรได้รับมอบหมายใหม่แล้ว foo = (bar > baz);ง่ายกว่ามาก
Eric

18

เช่นเดียวกับคำถามความคิดเห็นมากมายคำตอบก็คือ: ขึ้นอยู่กับมัน

สำหรับสิ่งที่ชอบ:

return x ? "Yes" : "No";

ฉันคิดว่ามันมากรัดกุมมากขึ้น (และเร็วสำหรับฉันที่จะแยกกว่า):

if (x) {
    return "Yes";
} else {
    return "No";
}

ทีนี้ถ้าการแสดงออกตามเงื่อนไขของคุณซับซ้อนการดำเนินการแบบไตรภาคไม่ใช่ทางเลือกที่ดี สิ่งที่ต้องการ:

x && y && z >= 10 && s.Length == 0 || !foo

ไม่ใช่ตัวเลือกที่ดีสำหรับผู้ประกอบการที่ประกอบไปด้วยคน

นอกจากนี้หากคุณเป็นโปรแกรมเมอร์ C GCC มีส่วนขยายที่อนุญาตให้คุณยกเว้นส่วนที่ประกอบไปด้วยสามส่วนที่เป็นจริงเช่นนี้:

/* 'y' is a char * */
const char *x = y ? : "Not set";

ซึ่งจะตั้งค่าxการyสมมติไม่ได้y NULLสิ่งที่ดี.


แก้ไขไวยากรณ์และไวยากรณ์เล็กน้อยฌอน :-) ไม่มีรหัส y จากบิตสุดท้ายและ "กำหนด x เป็น y" หมายถึง "y = x" ดังนั้นฉันจึงเปลี่ยนเป็น "set x to y"
paxdiablo

@Pax: ขอบคุณ! ฉันย้อนกลับการเปลี่ยนแปลงทางไวยากรณ์ตั้งแต่ฉันพยายามที่จะชี้ให้เห็นว่าด้วยส่วนขยาย GCC คุณไม่จำเป็นต้องมีส่วนที่เป็นจริงของไตรภาค
ฌอน Bright

ขออภัยไม่เห็นย่อหน้านั้น ไม่ทราบว่าฉันเห็นด้วยกับสิ่งนั้นแม้ว่าจะอนุญาตให้คนเขียนโค้ดที่จะไม่คอมไพล์ด้วยคอมไพเลอร์มาตรฐาน ISO แต่ถึงกระนั้นเมื่อ GCC เป็นคนสุดท้ายที่ยืนที่จะไม่เรื่อง :-)
paxdiablo

มันเป็นของขึ้นแน่นอน…และใครไม่ใช้ GCC : D
Sean Bright

14

ในความคิดของฉันมันเหมาะสมที่จะใช้ผู้ประกอบการที่สามในกรณีที่จำเป็นต้องมีการแสดงออก

ในกรณีอื่น ๆ ดูเหมือนว่าผู้ประกอบการที่ประกอบไปด้วยลดความชัดเจน


ปัญหาที่เกิดขึ้นคือ 99% ของภาษาการแสดงออกสามารถถูกแทนที่ด้วยฟังก์ชั่น ... และ ppl การหลีกเลี่ยงผู้ประกอบการที่ประกอบไปด้วยสามจะยิ่งต้องการโซลูชั่นที่
PierreBdR

11

โดยการวัดความซับซ้อนของวัฏจักรการใช้ifข้อความหรือผู้ประกอบการที่ประกอบไปด้วยกันนั้นเทียบเท่ากัน ดังนั้นโดยการวัดนั้นคำตอบคือไม่ความซับซ้อนจะเหมือนกันทุกประการ

โดยมาตรการอื่น ๆ เช่นความสามารถในการอ่านความสามารถในการบำรุงรักษาและ DRY (Don't-Repeat-Yourself) ตัวเลือกทั้งสองอาจพิสูจน์ได้ดีกว่าวิธีอื่น


10

ฉันใช้บ่อยในสถานที่ที่ฉันถูก จำกัด ให้ทำงานในนวกรรมิก - ตัวอย่างเช่น. NET 3.5 LINQ to XML constructs ใหม่ - เพื่อกำหนดค่าเริ่มต้นเมื่อพารามิเตอร์ทางเลือกเป็นโมฆะ

ตัวอย่างที่คาดหวัง:

var e = new XElement("Something",
    param == null ? new XElement("Value", "Default")
                  : new XElement("Value", param.ToString())
);

หรือ (ขอบคุณดาวเคราะห์น้อย)

var e = new XElement("Something",
    new XElement("Value",
        param == null ? "Default"
                      : param.ToString()
    )
);

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


หรือ ... var e = new XElement ("Something", XElement ใหม่ ("value", param == null? "Default": param.toString ()));
ดาวเคราะห์น้อย

2
ฉันชอบที่คุณกำลังจัดรูปแบบเพื่อให้อ่านได้หลายคนทำไม่ได้
bruceatk

รหัสแหล่งที่ดีของมนุษย์ที่อ่านได้ดีคืออะไรถ้ามันไม่สามารถอ่านได้ =)
Erik Forbes

9

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

มันทำให้ฉันสับสนอยู่เสมอว่าบางคนคิดว่าผู้ประกอบการที่ประกอบไปด้วยฟังก์ชั่น "ซ่อนเร้น" หรือค่อนข้างลึกลับ เป็นสิ่งแรกที่ฉันได้เรียนรู้เมื่อฉันเริ่มเขียนโปรแกรมใน C และฉันไม่คิดว่ามันจะลดความสามารถในการอ่านได้เลย มันเป็นส่วนที่เป็นธรรมชาติของภาษา


1
ฉันเห็นด้วยอย่างยิ่ง ไม่มีสิ่งใดที่ซ่อนเร้นอยู่
mmattax

2
มันสามารถทำให้เกิดปัญหาการอ่านโดยเฉพาะอย่างยิ่งเมื่อซ้อนกัน
David Thornley

ฉันคิดว่า " ยากมากที่จะอ่าน" เป็นบิตที่อนุญาตเกินไป แต่โดยรวมแล้วฉันเห็นด้วยกับคุณ ไม่มีอะไรยากหรือลึกลับเกี่ยวกับมัน
EpsilonVector

7

ฉันเห็นด้วยกับ jmulder: มันไม่ควรใช้แทน a if, แต่มันมีที่สำหรับใช้ในการแสดงออกทางกลับหรือภายในนิพจน์:

echo "Result: " + n + " meter" + (n != 1 ? "s" : "");
return a == null ? "null" : a;

อดีตเป็นเพียงตัวอย่างเท่านั้นควรใช้การสนับสนุนพหูพจน์ i18n ที่ดีกว่า!


Ternary แรกไม่ถูกต้อง - คุณมี: ที่ไหน ควรไป: (n! = 1 ? "s": "")
Erik Forbes

ใช่ขอบคุณที่ชี้ให้เห็น! แก้ไขแล้ว.
PhiLho

7

(แฮ็คของวัน)

#define IF(x) x ?
#define ELSE :

จากนั้นคุณสามารถทำ if-then-else เป็นนิพจน์:

int b = IF(condition1)    res1
        ELSE IF(condition2)  res2
        ELSE IF(conditions3) res3
        ELSE res4;

นี้ไม่ตอบคำถาม
Bruno Alexandre Rosa

6

หากคุณกำลังใช้ผู้ประกอบการที่สามสำหรับการกำหนดเงื่อนไขอย่างง่ายฉันคิดว่ามันใช้ได้ ฉันเคยเห็นมัน (ab) ใช้ในการควบคุมการไหลของโปรแกรมโดยไม่ต้องทำการมอบหมายและฉันคิดว่าควรหลีกเลี่ยง ใช้คำสั่ง if ในกรณีเหล่านี้


5

ฉันคิดว่าผู้ประกอบการที่ควรจะใช้เมื่อจำเป็น เห็นได้ชัดว่าเป็นตัวเลือกที่เป็นอัตนัย แต่ฉันพบว่าการแสดงออกอย่างง่าย ๆ (โดยเฉพาะการแสดงออกทางกลับ) นั้นชัดเจนกว่าการทดสอบเต็มรูปแบบ ตัวอย่างใน C / C ++:

return (a>0)?a:0;

เปรียบเทียบกับ:

if(a>0) return a;
else return 0;

คุณมีกรณีที่โซลูชันอยู่ระหว่างผู้ประกอบการที่ประกอบไปด้วยสามและการสร้างฟังก์ชั่น ตัวอย่างเช่นใน Python:

l = [ i if i > 0 else 0 for i in lst ]

ทางเลือกคือ:

def cap(value):
    if value > 0:
        return value
    return 0
l = [ cap(i) for i in lst ]

มีความจำเป็นพอที่ใน Python (เป็นตัวอย่าง) สำนวนดังกล่าวสามารถเห็นได้เป็นประจำ:

l = [ ((i>0 and [i]) or [0])[0] for i in lst ]

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


3
บรรทัดสุดท้ายนั้นทำให้สมองของฉันเจ็บ ...
Erik Forbes

5

ฉันชอบ 'em ฉันไม่รู้ว่าทำไม แต่ฉันรู้สึกเท่ห์มากเมื่อฉันใช้สำนวนที่ประกอบไปด้วยสาม


5

ฉันเคยเห็นสัตว์ร้ายเช่นนี้ (จริง ๆ แล้วมันแย่กว่าเดิมเพราะมันเป็น ValidateDate และตรวจสอบเดือนและวันเช่นกัน แต่ฉันไม่สามารถใส่ใจที่จะจดจำสิ่งทั้งหมดได้):

isLeapYear =
    ((yyyy % 400) == 0)
    ? 1
    : ((yyyy % 100) == 0)
        ? 0
        : ((yyyy % 4) == 0)
            ? 1
            : 0;

โดยที่ชัดถ้อยชัดคำชุดของ if-statement จะดีกว่า (แม้ว่าอันนี้ยังคงดีกว่ารุ่นแมโครที่ฉันเคยเห็น)

ฉันไม่รังเกียจสำหรับสิ่งเล็ก ๆ เช่น:

reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age;

หรือแม้แต่เรื่องยุ่งยากเล็กน้อยเช่น:

printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s");

คุณจะบอกชุดการแยกได้อย่างไรถ้าข้อความจะอ่านง่ายขึ้น? ฉันอ่าน "สัตว์ร้าย" ของคุณก็โอเค reportedAgeเป็นตัวอย่างที่ใช้เวลาคิดบางอย่าง - อาจเป็นเพราะมันเป็นกรณีพิเศษมากกว่าการหาisThisYearALeapYear
Axeman

4

ไวยากรณ์ของมันแย่มาก ฉันพบว่าฟังก์ชัน ifs มีประโยชน์มากและมักทำให้โค้ดอ่านง่ายขึ้น

ฉันขอแนะนำให้สร้างมาโครเพื่อให้อ่านได้ง่ายขึ้น แต่ฉันแน่ใจว่ามีบางคนที่สามารถสร้างเคสที่น่ากลัวได้ (เนื่องจาก CPP อยู่เสมอ)


การใช้งานพื้นฐานและตัวแปรหลายตัวมีฟังก์ชัน IF ที่เกิดขึ้นจากผู้ประกอบการที่ประกอบไปด้วยสามส่วน ฉันได้เห็นจำนวนของ codebases กับที่กำหนดไว้เป็นแมโครในซี
SPARR

ฉันคิดว่าภาษาโปรแกรมที่ใช้งานได้ แต่ใช่
Marcin

"การสร้างมาโครเพื่อให้อ่านง่ายขึ้น" คุณเป็นคนตลกมาก!
niXar

4

ฉันชอบใช้โอเปอเรเตอร์ในรหัสดีบั๊กเพื่อพิมพ์ค่าความผิดพลาดดังนั้นฉันจึงไม่ต้องค้นหามันตลอดเวลา ฉันมักจะทำสิ่งนี้เพื่อแก้ปัญหาการพิมพ์ที่จะไม่เหลืออยู่เมื่อฉันพัฒนาเสร็จแล้ว

int result = do_something();
if( result != 0 )
{
  debug_printf("Error while doing something, code %x (%s)\n", result,
                result == 7 ? "ERROR_YES" :
                result == 8 ? "ERROR_NO" :
                result == 9 ? "ERROR_FILE_NOT_FOUND" :
                "Unknown");
}


4

ฉันแทบจะไม่เคยใช้ผู้ประกอบการที่ประกอบไปด้วยเพราะเมื่อใดก็ตามที่ฉันใช้มันจะทำให้ฉันคิดมากกว่าที่ฉันต้องทำในภายหลังเมื่อฉันพยายามที่จะรักษามันไว้

ฉันชอบที่จะหลีกเลี่ยงการใช้คำฟุ่มเฟื่อย แต่เมื่อมันทำให้รหัสง่ายขึ้นมากที่จะรับฉันจะไปสำหรับ verbosity

พิจารณา:

String name = firstName;

if (middleName != null) {
    name += " " + middleName;
}

name += " " + lastName;

ตอนนี้มันค่อนข้างละเอียด แต่ฉันคิดว่ามันอ่านง่ายกว่า:

String name = firstName + (middleName == null ? "" : " " + middleName)
    + " " + lastName;

หรือ:

String name = firstName;
name += (middleName == null ? "" : " " + middleName);
name += " " + lastName;

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


1
นั่นไม่ใช่สิ่งเดียวกันเลย ในตัวอย่างที่สองคุณกำลังอัดคำสั่งทั้งสามให้เป็นหนึ่งบรรทัด นั่นคือสิ่งที่ลดความสามารถในการอ่านไม่ใช่ตัวดำเนินการประกอบ
ilitirit

ยุติธรรมพอฉันอัปเดตเพื่อรวมความคิดเห็นของคุณ แต่มันก็ยังรู้สึกว่ารก ... แต่อีกครั้งมันเป็นเรื่องส่วนตัว ... ฉันไม่ได้บอกว่าไม่สามารถอ่านได้แบบไตรภาคไม่ได้ฉันกำลังบอกว่ามันไม่สามารถอ่านได้ (99 % ของเวลา)
Mike Stone


3

ฉันมักจะใช้ในสิ่งต่าง ๆ เช่นนี้:

before:

if(isheader)
    drawtext(x,y,WHITE,string);
else
    drawtext(x,y,BLUE,string);

after:

    drawtext(x,y,isheader==true?WHITE:BLUE,string);

แน่นอนว่าในภาษาส่วนใหญ่คุณไม่ต้องการส่วน "== จริง" ของไตรภาคนั้น
Michael Haren

ฉันรู้ว่าถึงแม้ว่าฉันมักจะใส่มันในการทำให้โค้ดอ่านง่ายขึ้นเนื่องจากคอมไพเลอร์ควรปรับให้เหมาะสมกับสิ่งเดียวกันโดยไม่ต้องมี == true anyways
KPexEA

ในไม่มีภาษาที่คุณอาจต้อง "== จริง"
niXar

ฉันมีเวลาที่ยากลำบากในการตัดสินใจว่าจะโหวตหรือไม่ ตัวอย่างนั้นดี แต่ == TRUE เป็นสิ่งที่ฉันไม่สามารถเห็นได้ในรหัสของคนอื่น
Peter Perháč

3

เป็นคนอื่นได้ชี้ให้เห็นพวกเขาจะดีสำหรับเงื่อนไขง่าย ๆ ฉันชอบพวกเขาเป็นค่าเริ่มต้น (เช่น| |และหรือการใช้งานใน javascript และ python) เช่น

int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount;

การใช้งานทั่วไปอื่นคือการเริ่มต้นการอ้างอิงใน C ++ เนื่องจากการอ้างอิงจะต้องมีการประกาศและเริ่มต้นในคำสั่งเดียวกันคุณไม่สามารถใช้คำสั่ง if

SomeType& ref = pInput ? *pInput : somethingElse;

2
น่าทึ่งว่านี่เป็นการกล่าวถึงครั้งแรกของการอ้างอิงเริ่มต้นซึ่งเป็นหนึ่งในไม่กี่แห่งที่ไม่สามารถใช้ "ถ้า" แทนที่จะเป็น?: (ฉันเดาเพราะนี่ไม่ใช่คำถามเฉพาะ C ++ ... ) พวกเขายังมีประโยชน์ในรายการ initialisation ของนวกรรมิกด้วยเหตุผลเดียวกัน
j_random_hacker

2

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


2

ฉันเพิ่งเห็นการเปลี่ยนแปลงในผู้ประกอบการที่สาม (ดีเรียงลำดับ) ที่ทำให้มาตรฐาน "()?:" ตัวแปรดูเหมือนจะเป็นพารากอนของความชัดเจน:

var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)]

หรือเพื่อยกตัวอย่างที่เป็นรูปธรรมมากขึ้น:

var Name = ['Jane', 'John'][Gender == 'm'];

โปรดทราบว่านี่คือ Javascript ดังนั้นสิ่งต่าง ๆ ที่อาจเป็นไปไม่ได้ในภาษาอื่น (ขอบคุณ)


1
ว้าวมันแย่มาก! ลองนึกภาพซ้อนกันสองคน! สิ่งที่มีประโยชน์เพียงราง ๆ ที่ฉันเห็นก็คือถ้าคุณมีฟังก์ชั่นซึ่งส่งคืนอาร์เรย์ 2 องค์ประกอบ: var Name = getNames () [เพศ == 'm']; ... แต่นั่นก็น้อยกว่าที่อ่านได้!
nickf

2

สำหรับกรณีง่าย ๆ ฉันชอบที่จะใช้มัน ที่จริงแล้วมันง่ายต่อการอ่าน / รหัสเช่นพารามิเตอร์สำหรับฟังก์ชั่นหรือสิ่งต่าง ๆ เช่นนั้น นอกจากนี้เพื่อหลีกเลี่ยงการขึ้นบรรทัดใหม่ฉันชอบที่จะรักษาด้วยถ้าทั้งหมดของฉัน / อื่น

Neseting มันจะเป็นสิ่งที่ไม่ควรทำในหนังสือของฉัน

ดังนั้นการกลับมาทำงานอีกครั้งถ้า / อื่นฉันจะใช้ผู้ประกอบการที่ประกอบไปด้วย สำหรับกรณีอื่น ๆ ถ้าปกติ / อื่นถ้า / อื่น ๆ (หรือเปลี่ยน)


2

ฉันชอบกรณีพิเศษของ Groovy ของผู้ประกอบการที่เรียกว่าผู้ประกอบการที่เรียกว่า Elvis:?:

expr ?: default

รหัสนี้ประเมินว่า expr หากไม่ใช่โมฆะและเป็นค่าเริ่มต้นหากเป็น ในทางเทคนิคแล้วมันไม่ได้เป็นผู้ประกอบการไตรภาค แต่มันเกี่ยวข้องกับมันอย่างแน่นอนและประหยัดเวลา / การพิมพ์จำนวนมาก


ใช่ฉันรักสิ่งนั้นเช่นกัน - มัน??อยู่ใน C # ผู้ประกอบการโมฆะรวมกัน: stackoverflow.com/questions/278703/…
Jarrod Dixon

2

สำหรับงานง่าย ๆ เช่นการกำหนดค่าที่แตกต่างขึ้นอยู่กับเงื่อนไขว่ายอดเยี่ยม ฉันจะไม่ใช้มันเมื่อมีการแสดงออกที่ยาวขึ้นทั้งนี้ขึ้นอยู่กับเงื่อนไขของสรรพสิ่ง


2

คำตอบจำนวนมากได้กล่าวว่ามันขึ้นอยู่กับ ฉันพบว่าหากการเปรียบเทียบแบบไตรภาคไม่สามารถมองเห็นได้ในการสแกนรหัสอย่างรวดเร็วก็ไม่ควรใช้

ในฐานะที่เป็นปัญหาด้านข้างฉันอาจจะสังเกตได้ว่าการมีอยู่จริงของมันนั้นเป็นเรื่องผิดปกติเล็กน้อยเนื่องจากความจริงที่ว่าใน C การทดสอบเปรียบเทียบเป็นข้อความ ในไอคอนifโครงสร้าง (เช่นเดียวกับไอคอนส่วนใหญ่) เป็นนิพจน์จริง ดังนั้นคุณสามารถทำสิ่งต่าง ๆ เช่น:

x[if y > 5 then 5 else y] := "Y" 

... ซึ่งฉันพบว่าสามารถอ่านได้มากกว่าตัวดำเนินการเปรียบเทียบ ternery :-)

มีการสนทนาเมื่อเร็ว ๆ นี้เกี่ยวกับความเป็นไปได้ของการเพิ่ม?:ผู้ดำเนินการไปที่ไอคอน แต่หลายคนชี้ให้เห็นอย่างถูกต้องว่าไม่มีความจำเป็นอย่างยิ่งเพราะวิธีการifทำงาน

ซึ่งหมายความว่าหากคุณสามารถทำเช่นนั้นใน C (หรือภาษาอื่นใดที่มีผู้ดำเนินการ ternery) คุณจะไม่จำเป็นต้องมีผู้ดำเนินการ ternery เลย


2

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

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

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