?: ?? ตัวดำเนินการแทน IF | ELSE


85
public string Source
{
    get
    {
        /*
        if ( Source == null ){
            return string . Empty;
        } else {
            return Source;
        }
        */
        return Source ?? string.Empty;
    }
    set
    {
        /*
        if ( Source == null ) {
            Source = string . Empty;
        } else {
            if ( Source == value ) {
                Source = Source;
            } else {
                Source = value;
            }
        }
        */
        Source == value ? Source : value ?? string.Empty;
        RaisePropertyChanged ( "Source" );
    }
}

ฉันสามารถใช้?: ??โอเปอเรเตอร์ตรงตามเงื่อนไขหรืออื่น ๆ ได้หรือไม่


คำถามของฉัน:
เขียนต่อไปนี้ด้วย?: ?? ผู้ประกอบการ

[1]

if ( Source == null ){
    // Return Nothing
} else {
    return Source;
}

[2]

if ( Source == value ){
    // Do Nothing
} else {
    Source = value;
    RaisePropertyChanged ( "Source" );
} 

สั้น ๆ : จะทำอย่างไรไม่ส่งคืนอะไรเลยและทำหลาย ๆ คำสั่งกับ?: ??operator?


1
มันจะไม่ทำงานเหมือนกันอย่างไรก็ตาม การไม่ใช้การแยกสาขา if / else แบบมีเงื่อนไขแสดงว่าคุณกำหนดตัวแปรใหม่โดยไม่มีเงื่อนไข (และไม่จำเป็น) ทุกครั้งที่เข้าถึงตัวแปร ซึ่งอาจส่งผลเสียอย่างรวดเร็วโดยเฉพาะอย่างยิ่งหากคุณมีโค้ดแบบมัลติเธรด เพียงแค่ไม่ทำมัน
Jeff Mercado

1
คุณจะมีการโทรแบบไม่มีที่สิ้นสุด / เรียกซ้ำหากคุณสมบัติการรับของ Source กำลังส่งคืนคุณสมบัติ Source (get accessor)
John K

1
ข้อมูลโค้ดแรกของคุณมีความทะเยอทะยานทรัพย์สินที่เรียกหมาของตัวเองซึ่งจะซ้ำเรียกทะเยอทะยานของตัวเอง คุณสูญเสียฉันไปที่นั่นเพราะไม่มีทางที่จะเกิดขึ้นในสนามได้ โปรดปรับแต่งคำถามของคุณและอธิบายสิ่งที่คุณต้องการบรรลุ
Frédéric Hamidi

กลับไม่มีอะไร? นั่นคือ VB คุณกำลังเขียน c # ที่นี่
งาน

@ งานฉันหมายถึงวิธีการทำเช่นนั้นบรรทัดนี้เป็นความคิดเห็นสำหรับคำถาม
Ahmed Ghoneim

คำตอบ:


199

สำหรับ [1] คุณทำไม่ได้: ตัวดำเนินการเหล่านี้ถูกสร้างขึ้นเพื่อส่งคืนค่าไม่ใช่ดำเนินการ

การแสดงออก

a ? b : c

ประเมินbว่าaเป็นจริงและประเมินcว่าaเป็นเท็จหรือไม่

การแสดงออก

b ?? c

ประเมินbว่า if bไม่เป็นโมฆะและประเมินcว่า if bเป็นค่าว่าง

ถ้าคุณเขียน

return a ? b : c;

หรือ

return b ?? c;

พวกเขามักจะคืนบางสิ่งบางอย่าง

สำหรับ [2] คุณสามารถเขียนฟังก์ชันที่ส่งคืนค่าที่ถูกต้องซึ่งดำเนินการ "หลายการดำเนินการ" ของคุณได้ แต่อาจแย่กว่าการใช้เพียงif/elseอย่างเดียว


41

ตัวดำเนินการ ternary ( ?:) ไม่ได้ออกแบบมาสำหรับโฟลว์การควบคุมซึ่งออกแบบมาสำหรับการกำหนดเงื่อนไขเท่านั้น หากคุณจำเป็นต้องควบคุมการไหลของโปรแกรมของคุณใช้โครงสร้างการควบคุมเช่น/ifelse


5
ฉันจะเพิ่มว่าฉันเคยเห็นคนใช้นิพจน์ ternary ที่ซ้อนกันแทน if / else และมันสร้างโค้ดที่อ่านยากและดีบัก Mojo ไม่ดีทุกรอบ
ckramer

4
บางครั้งตัวดำเนินการ ternary ที่ซ้อนกันจะสร้างโค้ดที่อ่านได้มากขึ้นหากใช้ช่องว่างอย่างเหมาะสม
trutheality

2
@truth: ใช่ฉันไม่มีอะไรต่อต้านซ้อน?:ต่อ se แต่ฉันมีปัญหาใหญ่กับการใช้โฟลว์การควบคุมและโฟลว์ควบคุมที่ซ้อนกันโดยเฉพาะ!
Oliver Charlesworth

11

อ้างถึง?: Operator (C # Reference)

ตัวดำเนินการตามเงื่อนไข (? :) ส่งกลับค่าหนึ่งในสองค่าขึ้นอยู่กับค่าของนิพจน์บูลีน ต่อไปนี้เป็นไวยากรณ์สำหรับตัวดำเนินการตามเงื่อนไข

หมายถึง?? ตัวดำเนินการ (อ้างอิง C #)

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

นั่นหมายความว่า:

[ส่วนที่ 1]

return source ?? String.Empty;

[ตอนที่ 2] ใช้ไม่ได้ ...


3
นั่นต่างจากการไม่ทำอะไรเลย ส่งคืนสตริงว่างเปล่า
trutheality

1
แน่นอน แต่นั่นไม่ใช่สิ่งที่ OP ขอ ไม่ใช่ความผิดของฉันที่ OP ขอให้ "ไม่คืนอะไร" - อะไรก็ได้ที่อาจหมายถึง
trutheality

1
@trutheality: ไม่มีร่างใดบอกว่ามันเป็นความผิดของคุณ .. อย่างไรก็ตาม OP ไม่ต้องการคืนอะไรเลยและสิ่งที่ฉันให้ไว้
Akram Shahda

3

"ไม่ทำอะไร" ใช้ไม่ได้จริงหรือ?

ถ้าโดย // Return Nothing จริง ๆ แล้วคุณหมายถึง return null จากนั้นเขียน

return Source;

ถ้าคุณหมายถึงให้ละเว้น codepath แล้วเขียน

 if ( Source != null )
            {
                return Source;
            }
// source is null so continue on.

และสำหรับครั้งสุดท้าย

 if ( Source != value )
            { Source = value;
                RaisePropertyChanged ( "Source" );
            }

// nothing done.

3

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

bar ? () : baz();

ในกรณีนี้ () ไม่ทำอะไรเลยในขณะที่ baz ทำอะไรบางอย่าง แต่คุณทำให้โค้ดมีความชัดเจนน้อยลง ฉันจะหาโค้ด verbose เพิ่มเติมที่ชัดเจนและดูแลรักษาง่ายกว่า

นอกจากนี้สิ่งนี้มีเหตุผลเล็กน้อยเลย:

var foo = bar ? () : baz();

เนื่องจาก () ไม่มีประเภทการส่งคืน (เป็นโมฆะ) และ baz มีประเภทการส่งคืนที่ไม่ทราบที่จุดเรียกในตัวอย่างนี้ หากพวกเขาไม่เห็นด้วยผู้รวบรวมจะบ่นและส่งเสียงดัง


2

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

if (Source == value) return;
Source = value;
RaisePropertyChanged("Source");

ฉันไม่ได้ดูถูกเหยียดหยามฉันแค่คิด!
Ahmed Ghoneim

1

the?: เป็นผู้ดำเนินการกำหนดการเดินทาง (เชื่อว่าฉันสะกดถูก) และใช้งานง่าย เช่นเดียวกับเพรดิเคตบูลีน? iftrue: ifalse; แต่คุณต้องมี rvalue / lvalue ใน rvalue = predicate? iftrue: iffalse;

เช่น int i = x < 7 ? x : 7;

ถ้า x น้อยกว่า 7 ฉันจะได้รับมอบหมาย x ถ้าไม่ใช่ฉันจะเป็น 7

คุณยังสามารถใช้ในทางกลับกันได้เช่นกัน return x < 7 ? x : 7;

อีกครั้งดังข้างต้นสิ่งนี้จะมีผลเช่นเดียวกัน

ดังนั้นSource = Source == value ? Source : string.Empty;ฉันเชื่อว่าเป็นสิ่งที่คุณพยายามจะบรรลุ


6
ฉันชอบมัน. ประกอบการเดินทาง : มันจะช่วยให้คุณได้รับจาก A ไป B ... หรือจาก A ถึง C ... ขึ้นอยู่กับเอ
ริก Sladkey

ใช่เขาหมายถึงคนสามคน แต่ชื่อที่ถูกต้องคือ "conditional"
Erick G. Hagstrom

1

ตัว?:ดำเนินการส่งคืนค่าหนึ่งในสองค่าขึ้นอยู่กับค่าของนิพจน์บูลีน

Condition-Expression ? Expression1 : Expression2

ค้นหาข้อมูลเพิ่มเติมเกี่ยวกับ?:โอเปอเรเตอร์หรือที่เรียกว่า Ternary Operator ได้ที่นี่:


0

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

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