return myVar กับ return (myVar) ต่างกันหรือไม่


87

ฉันกำลังดูตัวอย่างรหัส C # และสังเกตเห็นว่าตัวอย่างหนึ่งห่อผลตอบแทนไว้ใน ()

ฉันทำมาตลอด:

return myRV;

มีความแตกต่างในการทำ:

return (myRV);

คำตอบ:


229

UPDATE: คำถามนี้เป็นเรื่องของการบล็อกของฉันบน 12 เมษายน 2010 ขอบคุณสำหรับคำถามที่น่าขบขัน!

ในทางปฏิบัติไม่แตกต่างกัน

ในทางทฤษฎีอาจมีความแตกต่าง มีประเด็นที่น่าสนใจสามประการในข้อกำหนด C # ซึ่งอาจทำให้เกิดความแตกต่างได้

ขั้นแรกการแปลงฟังก์ชันที่ไม่ระบุชื่อเพื่อมอบหมายชนิดและแผนภูมินิพจน์ พิจารณาสิ่งต่อไปนี้:

Func<int> F1() { return ()=>1; }
Func<int> F2() { return (()=>1); }

F1ถูกกฎหมายอย่างชัดเจน คือF2? ในทางเทคนิคไม่ ข้อมูลจำเพาะระบุไว้ในส่วน 6.5 ว่ามีการแปลงจากนิพจน์แลมบ์ดาเป็นประเภทผู้ร่วมประชุมที่เข้ากันได้ นั่นคือการแสดงออกของแลมด้าหรือไม่? เลขที่มันเป็นแสดงออกวงเล็บที่มีการแสดงออกแลมบ์ดา

คอมไพเลอร์ Visual C # ละเมิดข้อกำหนดเล็กน้อยที่นี่และทิ้งวงเล็บให้คุณ

ประการที่สอง:

int M() { return 1; }
Func<int> F3() { return M; }
Func<int> F4() { return (M); }

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

ประการที่สาม:

enum E { None }
E F5() { return 0; }
E F6() { return (0); }

F5ถูกกฎหมาย คือF6? ไม่ใช่ข้อมูลจำเพาะระบุว่ามีการแปลงจากศูนย์ตามตัวอักษรเป็นประเภทที่แจกแจงใด ๆ " (0)" ไม่ใช่ศูนย์ตามตัวอักษร แต่เป็นวงเล็บตามด้วยศูนย์ตัวอักษรตามด้วยวงเล็บ เราละเมิดข้อกำหนดที่นี่และอนุญาตให้นิพจน์คงที่ของเวลาคอมไพล์มีค่าเท่ากับศูนย์ไม่ใช่แค่ศูนย์ตามตัวอักษรเท่านั้น

ดังนั้นในทุกกรณีเราอนุญาตให้คุณหลีกเลี่ยงแม้ว่าในทางเทคนิคแล้วการทำเช่นนั้นจะผิดกฎหมาย


12
@ เจสัน: ฉันเชื่อว่าการละเมิดข้อมูลจำเพาะในสองกรณีแรกเป็นเพียงข้อผิดพลาดที่ไม่เคยถูกจับได้ การส่งผ่านการผูกครั้งแรกในอดีตมีความก้าวร้าวอย่างมากเกี่ยวกับการปรับนิพจน์ให้เหมาะสมก่อนเวลาอันควรและหนึ่งในผลที่ตามมาคือวงเล็บจะถูกทิ้งเร็วกว่าที่ควร ในทุกๆกรณีทั้งหมดนี้ทำให้โปรแกรมที่เห็นได้ชัดโดยสังหรณ์ใจทำงานได้อย่างที่ควรจะเป็นดังนั้นฉันจึงไม่กังวลมากนัก วิเคราะห์คดีที่สามได้ที่: blogs.msdn.com/ericlippert/archive/2006/03/28/…
Eric Lippert

6
ในทางทฤษฎีในทางปฏิบัติมีคือความแตกต่าง (ฉันไม่แน่ใจว่าโมโนช่วยให้ทั้ง 3 กรณีและไม่ทราบว่าของคอมไพเลอร์อื่น ๆ ใด ๆ C # ดังนั้นอาจหรืออาจจะไม่แตกต่างกันในทางปฏิบัติในทางปฏิบัติ) การละเมิดข้อกำหนด C # หมายความว่ารหัสของคุณจะไม่สามารถพกพาได้อย่างสมบูรณ์ คอมไพเลอร์ C # บางตัวอาจแตกต่างจาก Visual C # ไม่ละเมิดข้อมูลจำเพาะในกรณีเฉพาะเหล่านั้น
Brian

18
@ Bruno: ทั้งหมดนี้ใช้เวลาประมาณแปดหรือหมื่นชั่วโมงในการศึกษาเรื่องที่กำหนดและคุณก็สามารถเป็นผู้เชี่ยวชาญได้เช่นกัน ซึ่งทำได้ง่ายในสี่ปีของการทำงานเต็มเวลา
Eric Lippert

32
@Anthony: ตอนที่ผมทำอย่างนั้นผมแค่บอกคนว่าระดับของฉันอยู่ในคณิตศาสตร์ไม่เลขคณิต
Eric Lippert

7
ในทางทฤษฎีการปฏิบัติและทฤษฎีเหมือนกัน แต่ในทางปฏิบัติพวกเขาไม่เคยเป็น
อิบราฮิมฮาชิมิ

40

มีหลายกรณีที่การมีวงเล็บอาจมีผลต่อพฤติกรรมของโปรแกรม:

1.

using System;

class A
{
    static void Foo(string x, Action<Action> y) { Console.WriteLine(1); }
    static void Foo(object x, Func<Func<int>, int> y) { Console.WriteLine(2); }

    static void Main()
    {
        Foo(null, x => x()); // Prints 1
        Foo(null, x => (x())); // Prints 2
    }
}

2.

using System;

class A
{
    public A Select(Func<A, A> f)
    {
        Console.WriteLine(1);
        return new A();
    }

    public A Where(Func<A, bool> f)
    {
        return new A();
    }

    static void Main()
    {
        object x;
        x = from y in new A() where true select (y); // Prints 1
        x = from y in new A() where true select y; // Prints nothing
    }
}

3.

using System;

class Program
{
    static void Main()
    {
        Bar(x => (x).Foo(), ""); // Prints 1
        Bar(x => ((x).Foo)(), ""); // Prints 2
    }

    static void Bar(Action<C<int>> x, string y) { Console.WriteLine(1); }
    static void Bar(Action<C<Action>> x, object y) { Console.WriteLine(2); }
}

static class B
{
    public static void Foo(this object x) { }
}

class C<T>
{
    public T Foo;
}

หวังว่าคุณจะไม่เห็นสิ่งนี้ในทางปฏิบัติ


ไม่ใช่คำตอบสำหรับคำถามของฉัน แต่ก็ยังน่าสนใจ - ขอบคุณ
chris

1
คุณอธิบายได้ไหมว่าเกิดอะไรขึ้นใน 2 ที่นี่?
Eric

2
คุณควรอธิบายอย่างละเอียดว่าเหตุใดจึงเกิดพฤติกรรมนี้
Arturo Torres Sánchez


3

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


6
นั่นจะตอบคำถามสำหรับกรณีเฉพาะอย่างแน่นอน แต่นั่นไม่จำเป็นต้องเป็นตัวแทนของสถานการณ์ทั้งหมด
Beska

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