Làm thế nào tôi có thể gọi phương thức mặc định thay vì triển khai cụ thể


9

Tại sao hành vi của Phương thức giao diện mặc định thay đổi trong C # 8? Trước đây, đoạn mã sau (Khi các phương thức giao diện Mặc định là bản demo không được phát hành):

interface IDefaultInterfaceMethod
{
    // By default, this method will be virtual, and the virtual keyword can be here used!
    virtual void DefaultMethod()
    {
        Console.WriteLine("I am a default method in the interface!");
    }

}

interface IOverrideDefaultInterfaceMethod : IDefaultInterfaceMethod
{
    void IDefaultInterfaceMethod.DefaultMethod()
    {
        Console.WriteLine("I am an overridden default method!");
    }
}

class AnyClass : IDefaultInterfaceMethod, IOverrideDefaultInterfaceMethod
{
}

class Program
{
    static void Main()
    {
        IDefaultInterfaceMethod anyClass = new AnyClass();
        anyClass.DefaultMethod();

        IOverrideDefaultInterfaceMethod anyClassOverridden = new AnyClass();
        anyClassOverridden.DefaultMethod();
    }
}

có đầu ra sau:

Bảng điều khiển đầu ra:

Tôi là một phương thức mặc định trong giao diện!
Tôi là một phương thức mặc định bị ghi đè!

Nhưng với phiên bản cuối cùng của C # 8, đoạn mã trên đang tạo ra kết quả sau:

Bảng điều khiển đầu ra:

Tôi là một phương thức mặc định bị ghi đè!
Tôi là một phương thức mặc định bị ghi đè!

Bất cứ ai cũng có thể giải thích cho tôi tại sao hành vi này được thay đổi?

Ghi chú:

IDefaultInterfaceMethod anyClass = new AnyClass(); anyClass.DefaultMethod();

((IDefaultInterfaceMethod) anyClass).DefaultMethod(); // STILL the same problem!??

2
Không có phương thức giao diện mặc định nào trước C # 8. Đầu ra thứ hai là trường hợp dự kiến ​​- khi bạn thực hiện một phương thức giao diện, bạn mong đợi sẽ được gọi. Bạn đang đề cập đến một đặc điểm kỹ thuật cũ hơn có lẽ? Tôi hy vọng nó đã bị bỏ rơi vì nó phá vỡ hành vi dự kiến ​​của một phương thức giao diện
Panagiotis Kanavos

3
Một câu hỏi tốt hơn sẽ là "làm thế nào tôi có thể gọi phương thức mặc định thay vì triển khai cụ thể?" câu trả lời là "bạn chưa thể, bởi vì cú pháp base.DefaultMethod () đã bị loại bỏ khỏi C # 8"
Panagiotis Kanavos

4
Đây là trang họp thiết kế nơi các cuộc gọi cơ sở đã được thảo luận và bỏ qua cho C # 8 Cut base() syntax for C# 8. We intend to bring this back in the next major release.. Điều này sẽ yêu cầu hỗ trợ thời gian chạy để hoạt động đúng.
Panagiotis Kanavos

3
Một giao diện là một giao diện luôn. Khi tôi thực hiện một phương thức giao diện, tôi hy vọng tất cả các máy khách sẽ gọi phương thức đã thực hiện. Khách hàng không nên quan tâm lớp nào thực hiện phương thức - họ có giao diện và họ gọi nó.
Panagiotis Kanavos

2
Đối với cú pháp bạn đã đăng, nó phải xuất phát từ một đề xuất thực sự cũ - DIM chỉ có thể được gọi một cách rõ ràng, giống như các giao diện được triển khai rõ ràng. Xét đề nghị rằng, mặc dù sử dụng cú pháp giao diện rõ ràng để ... làm việc đối diện của virtualtôi đoán? Và có thể giới thiệu một viên kim cương thừa kế
Panagiotis Kanavos

Câu trả lời:


6

Tôi nghi ngờ một câu hỏi tốt hơn sẽ là:

Làm thế nào tôi có thể gọi phương thức mặc định thay vì thực hiện cụ thể?

Tính năng này đã được lên kế hoạch nhưng đã bị cắt khỏi C # 8 vào tháng 4 năm 2019 , bởi vì việc triển khai hiệu quả sẽ cần sự hỗ trợ từ thời gian chạy. Điều này không thể được thêm vào trong thời gian trước khi phát hành. Tính năng này sẽ phải hoạt động tốt cho cả C # và VB.NET - F # không thích giao diện nào.

nếu BM không có mặt trong thời gian chạy, AM () sẽ được gọi. Đối với cơ sở () và giao diện, điều này không được hỗ trợ bởi thời gian chạy, vì vậy cuộc gọi sẽ đưa ra một ngoại lệ thay thế. Chúng tôi muốn thêm hỗ trợ cho việc này trong thời gian chạy, nhưng quá tốn kém để thực hiện bản phát hành này.

Chúng tôi có một số cách giải quyết, nhưng họ không có hành vi mà chúng tôi muốn và không phải là loại tiền mã hóa ưa thích.

Việc triển khai C # của chúng tôi có phần khả thi, mặc dù không chính xác như những gì chúng tôi muốn, nhưng việc triển khai VB sẽ khó khăn hơn nhiều. Hơn nữa, việc triển khai VB sẽ yêu cầu các phương thức triển khai giao diện phải là bề mặt API công khai.

Nó sẽ hoạt động thông qua một base()cuộc gọi tương tự như cách các lớp học hoạt động. Sao chép ví dụ đề xuất:

interface I1
{ 
    void M(int) { }
}

interface I2
{
    void M(short) { }
}

interface I3
{
    override void I1.M(int) { }
}

interface I4 : I3
{
    void M2()
    {
        base(I3).M(0) // What does this do?
    }
}

Tôi sẽ để nó một lúc trước khi đánh dấu câu trả lời. có thể bạn sẽ nhận được một số phiếu bầu cho công việc tốt của bạn :-) cảm ơn bạn!
Bassam Alugili

1
@BassamAlugili chỉ vì ai đó đã hỏi một cái gì đó tương tự một tháng trước. Sau đó tôi mặc dù Why would you do that?. Sau đó tôi phát hiện ra biên bản cuộc họp
Panagiotis Kanavos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.