2015-04-14 15 views
5

Tại sao tôi không được phép có phương pháp tĩnh và không tĩnh với cùng một chữ ký?Cuộc gọi không rõ ràng giữa các phương pháp hoặc thuộc tính sau đây (một tĩnh và một không tĩnh)

Hãy nói rằng tôi có một lớp học như thế này

public class TestClass 
{ 
    public object thing { get; set; } 

    public TestClass() 
    { 

    } 

    public TestClass(object thing) 
    { 
     this.thing = thing; 
    } 

    public static TestClass ConvertTestClass(object thing) 
    { 
     return new TestClass(thing); 
    } 

    public TestClass ConvertTestClass(object thing) 
    { 
     this.thing = thing; 
     return this; 
    } 


} 

và tôi cố gắng sử dụng nó như thế này

public class SomeOtherClass 
{ 
    public SomeOtherClass() 
    { 
     TestClass tc = TestClass.ConvertTestClass(new object()); 

     TestClass tc2 = new TestClass(); 
     tc2.ConvertTestClass(new object()); 
    } 
} 

tôi nhận được các lỗi sau đây trên TestClass.ConvertTestClass(new object());

Cuộc gọi là không rõ ràng giữa các phương thức hoặc thuộc tính sau: 'TestClass.ConvertTestClass (đối tượng)' và 'TestClass.ConvertTestClass (đối tượng)'

và các lỗi trên tc2.ConvertTestClass(new object());

Cuộc gọi là mơ hồ giữa các phương thức hoặc thuộc tính sau: 'TestClass.ConvertTestClass (object)' và 'TestClass.ConvertTestClass (object)'

Thành viên 'TestClass.ConvertTestClass (đối tượng)' không thể được truy cập với một tham chiếu cá thể; hội đủ điều kiện với tên loại thay thế

Trình biên dịch có thực sự không cho biết sự khác biệt giữa các phiên bản tĩnh và không tĩnh của phương pháp đó hay tôi thiếu gì đó ở đây?

Tôi không sử dụng ReSharper (dường như là gốc của một vấn đề tương tự trong các câu hỏi khác).

+3

Bạn mong đợi điều gì sẽ được gọi với chỉ 'ConvertTestClass (đối tượng mới())' từ bên trong 'TestClass'? ;) Nhưng cuối cùng nó có lẽ là một quyết định thiết kế vì lợi ích của sự rõ ràng. – Marvin

+0

@Marvin chắc chắn sẽ mơ hồ. Nhưng, sẽ không nói hoặc 'this.ConvertTestClass' hoặc' TestClass.ConvertTestClass' giải quyết sự mơ hồ? Đôi khi chúng tôi được yêu cầu làm điều đó làm rõ về trình biên dịch ('System.Windows.Shapes.Path' /' System.IO.Path') – Brad

+1

Hãy xem [answer] này (http://stackoverflow.com)/a/6033530/3052062) bởi Jon Skeet – chomba

Trả lời

4

Nó cho bạn một lỗi, do đó, đặt cược an toàn mà trình biên dịch không thể, hoặc sẽ không, phân biệt giữa hai phương pháp.

Có lẽ đây là một ý tưởng tồi khi thực hiện loại quá tải này, vì không rõ phương pháp bạn đang định gọi, nhưng nếu điều đó không đủ, đặc tả C# 5 xác định chữ ký phương thức như thế này (Phần 3.6) :

chữ ký của một phương pháp bao gồm tên của phương pháp, số các thông số chủng loại và kiểu và loại (giá trị, tài liệu tham khảo, hoặc đầu ra) của mỗi thông số chính thức của nó, xem xét trong để lại sang phải. Đối với các mục đích này, bất kỳ tham số kiểu nào của phương thức xảy ra trong loại thông số chính thức được xác định không phải bởi tên , nhưng theo vị trí thứ tự của nó trong danh sách đối số kiểu của phương thức . Chữ ký của một phương thức cụ thể không bao gồm loại trả về , công cụ sửa đổi thông số có thể được chỉ định cho tham số ngoài cùng bên phải , cũng như các ràng buộc tham số kiểu tùy chọn.

Nó không đề cập rõ ràng static, nhưng nó cũng không bao gồm nó như là một phần của định nghĩa "chữ ký". Vì vậy, công bằng của nó để giả định rằng bởi spec, một quá tải phương thức không thể khác nhau chỉ trong thực tế là nó là tĩnh hoặc instanced.

+0

Mục 7.6.4 và Phần 10.6.2 * dường như * để đề xuất trình biên dịch có thể nói khác nhau. Tôi có nghĩa là điều này thường được cho phép 'this.thing = thing;'. – Brad

+0

@Brad Đọc ngay bây giờ, nhưng tôi chưa bao giờ nói trình biên dịch không hiểu cách 'tĩnh' hoạt động, chỉ vì nó không phải là một phần của chữ ký cho mục đích quá tải. – BradleyDotNET

+0

Vâng, tôi nghe ya. Đây chỉ là "đó là cách nó là" loại điều có thể. – Brad

0

Tôi muốn viết bài này làm nhận xét tuy nhiên sẽ dễ dàng hơn để làm cho điểm này trong trình chỉnh sửa phù hợp.

Tôi nghĩ bạn chỉ đang nghĩ về logic của các phương thức gọi trên lớp bên ngoài, tức là từ một lớp khác. Trong các phương thức lớp với cùng một chữ ký chỉ khác nhau bởi tĩnh không có ý nghĩa gì cả. ví dụ: bạn có một lớp học với hai phương pháp như sau

public class MyClass 
{ 
    public static void HellowWorld() 
    { 
     Console.WriteLine("Hello World!"); 
    } 

    public void HellowWorld() 
    { 
     Console.WriteLine("Howdy World!"); 
    } 

    public void Greet() 
    { 
     HellowWorld(); 
    } 
} 

Khi biên dịch bạn sẽ thấy miễn là một trong các phương pháp được nhận xét không biên dịch mà không có lỗi. Bạn sẽ có thể thay thế phương thức nhận xét và biên dịch thành công lớp. Chỉ ra không có cách nào để phân biệt phương thức nào nên được gọi trong phạm vi của lớp.

Bạn có thể tranh luận rằng trong lớp, bạn nên bắt buộc phải sử dụng cùng một cú pháp để gọi phương thức tĩnh như bạn làm bên ngoài, ví dụ:

Tuy nhiên, điều này sẽ thách thức phạm vi logic được sử dụng trong suốt C#, tại sao bạn cần chỉ định tên lớp trong lớp? Tôi nghĩ rằng một sự thay đổi như vậy cũng sẽ tạo ra sự mơ hồ nơi mà không ai, và để làm như vậy bây giờ tất nhiên sẽ phá vỡ rất nhiều mã ra khỏi đó.

Tôi nghĩ rằng logic trình biên dịch vì nó có ý nghĩa hoàn hảo.

Các vấn đề liên quan