อะไรคือความแตกต่างระหว่างการใช้อินเทอร์เฟซอย่างชัดเจนหรือโดยปริยาย?


64

ใน Visual Studio ฉันสามารถคลิกขวาที่อินเทอร์เฟซและเลือกที่จะใช้อินเตอร์เฟสหรือใช้อินเตอร์เฟสได้อย่างชัดเจน

โปรแกรม Visual Studio

public class Test : ITest
{
    public string Id // Generated by Implement Interface
    {
        get { throw new NotImplementedException(); }
    }

    string ITest.Id // Generated by Implement Interface Explicitly
    {
        get { throw new NotImplementedException(); }
    }
}

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

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

คำตอบ:


51

ตรวจสอบคำตอบจากด้านบนแอนดรูบาร์เร็ตต์สำหรับ"นัย VS ใช้อินเตอร์เฟซที่ชัดเจน" ในดังนั้น

โดยทั่วไป:

  • โดยนัย: คุณเข้าถึงวิธีการและคุณสมบัติของอินเตอร์เฟสเสมือนว่าเป็นส่วนหนึ่งของคลาส
  • อย่างชัดเจน: คุณสามารถเข้าถึงวิธีการและคุณสมบัติได้เมื่อปฏิบัติต่อคลาสเป็นอินเทอร์เฟซที่ใช้งานแล้ว

ตัวอย่างรหัส:

โดยปริยาย:

Test t = new Test();
t.Id; // OK
((ITest)t).Id; // OK

ชัดเจน:

Test t = new Test();
t.Id; // Not OK
((ITest)t).Id; // OK

ในแง่ของ "เมื่อ" คุณต้องใช้อินเทอร์เฟซอย่างชัดเจนนั่นคือเมื่อคลาสของคุณมีเมธอดที่มีลายเซ็นเดียวกันกับหนึ่งในเมธอดของอินเทอร์เฟซของคุณอยู่แล้วหรือเมื่อคลาสของคุณใช้อินเทอร์เฟซหลายตัว แต่สัญญาที่เข้ากันไม่ได้


1
ฉันยังพบว่าการใช้งานที่ชัดเจนมีประโยชน์ในการจัดเรียงส่วนต่อประสาน "ที่ซ่อนอยู่" กับการทำงานที่ไม่ปลอดภัย นอกจากนี้ยังทำให้การเรียกใช้วิธีการเหล่านั้นโดดเด่นมากขึ้นซึ่งเป็นสิ่งที่ดีสำหรับสิ่งที่ไม่ปลอดภัย
Tamás Szelei

นอกจากนี้ยังมีมูลค่าการกล่าวขวัญว่ามีค่าใช้จ่ายประสิทธิภาพในการใช้อินเทอร์เฟซที่ชัดเจนเนื่องจากมันจำเป็นต้องกล่อง / unbox วัตถุเมื่อใดก็ตามที่คุณอ้างอิงคุณสมบัติ / วิธีการ ด้วยเหตุนี้จึงเป็นการดีกว่าถ้าจะใช้อินเทอร์เฟซโดยปริยายถ้าเป็นไปได้
Rachel

3
@Rachel: เท่าที่ฉันทราบว่าค่าใช้จ่ายประสิทธิภาพจะมีผลเฉพาะกับประเภทค่า
Groky

8

นอกจากนี้ยังมีความแตกต่างในวิธีการที่คุณเรียกวิธีการ

เมื่อใช้การใช้งานอินเทอร์เฟซที่ชัดเจนคุณต้องใช้ประเภทอินเตอร์เฟสเพื่อเรียกใช้งานเฉพาะนั้น

ดังนั้นในการเรียกรหัสที่คุณจะต้องใช้ตัวแปรของชนิดเพื่อที่จะเข้าถึงITestITest.Id

บทความการใช้อินเทอร์เฟซที่ชัดเจน (คู่มือการเขียนโปรแกรม C #)บน MSDN มีตัวอย่างที่ดี


4

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

โปรดดู: บทแนะนำการใช้งานอินเตอร์เฟสอย่างชัดเจน


4

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

public interface ITest
{
    string Id { get; }
}

public interface IAlsoTest
{
    string Id { get; }
}

public interface ITestToo
{
    int Id { get; }
}

public class Test : ITest, IAlsoTest
{
    // Valid implicit implementation of BOTH interfaces
    public string Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestSeparately : ITest, ITestToo
{
    // This way we can do different things depending
    // on which interface the callee called from.
    string ITest.Id
    {
        get { throw new NotImplementedException(); }
    }

    int ITestToo.Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestOuch
{
    public void DoStuff()
    {
        var ts = new TestSeparately();

        // Works
        Console.WriteLine(((ITest)ts).Id);

        // Works
        Console.WriteLine(((ITestToo)ts).Id);

        // Not valid! Which one did we want to call?
        Console.WriteLine(ts.Id);
    }
}

การใช้ตัวอย่างเก็บไว้เมื่อคุณใช้สมาชิกอินเทอร์เฟซอย่างชัดเจนแม้ว่าคุณจะใช้อินเทอร์เฟซเดียวเท่านั้น (ซึ่งฉันมักจะลืม: S) ดังนั้นฉันจะลองและหลีกเลี่ยงการใช้งานอย่างชัดเจนทุกครั้งที่เป็นไปได้ ไม่ได้ส่งไปยังอินเทอร์เฟซที่ถูกต้อง (ซึ่งค่อนข้างสับสน)


3

ตามคำตอบของ Jalayan

  • โดยนัย: คุณเข้าถึงวิธีการและคุณสมบัติของอินเตอร์เฟสเสมือนว่าเป็นส่วนหนึ่งของคลาส
  • อย่างชัดเจน: คุณสามารถเข้าถึงวิธีการและคุณสมบัติได้เมื่อปฏิบัติต่อคลาสเป็นอินเทอร์เฟซที่ใช้งานแล้ว

ป้อนคำอธิบายรูปภาพที่นี่

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