2008-10-01 24 views
47

Tôi có một lớp với giao diện tĩnh và không tĩnh trong C#. Có thể có một phương thức tĩnh và không tĩnh trong một lớp có cùng tên và chữ ký không?Phương pháp tĩnh và sơ thẩm có cùng tên?

Tôi gặp lỗi trình biên dịch khi cố gắng thực hiện điều này, nhưng vì lý do nào đó, tôi nghĩ có cách để thực hiện việc này. Tôi có sai hay không có cách nào để có cả phương pháp tĩnh và không tĩnh trong cùng một lớp?

Nếu điều này là không thể, có cách nào tốt để thực hiện một cái gì đó như thế này mà có thể được áp dụng chung cho mọi tình huống?

EDIT
Từ các câu trả lời tôi đã nhận được, rõ ràng là không có cách nào để thực hiện việc này. Tôi đang đi với một hệ thống đặt tên khác nhau để giải quyết vấn đề này.

+0

Bạn có thể cung cấp ví dụ về nơi bạn có thể muốn thực hiện việc này không? –

+1

Tôi không khuyên bạn nên dựa vào sự khác biệt trong trường hợp để phân biệt hai phương pháp. Ý tưởng thực sự tồi. Bạn không bao giờ nên có hai phương pháp chỉ khác nhau trong trường hợp: Tôi đảm bảo rằng bạn sẽ kết thúc việc gọi sai. –

+3

Đổi tên các phương thức thành các tên khác nhau. Dựa vào trường hợp không an toàn, đặc biệt nếu có cơ hội mã được biên dịch sẽ được sử dụng bởi ngôn ngữ .NET khác không phân biệt chữ hoa chữ thường. Chỉ vì ngôn ngữ có phân biệt chữ hoa chữ thường, bạn nên dựa vào thực tế đó để phân biệt tên phương thức. –

Trả lời

52

Không, bạn không thể. Lý do cho giới hạn là các phương thức tĩnh cũng có thể được gọi từ các ngữ cảnh không tĩnh mà không cần phải thêm vào tên lớp (vì vậy MyStaticMethod() thay vì MyClass.MyStaticMethod()). Trình biên dịch không thể cho biết bạn đang tìm kiếm gì nếu bạn có cả hai.

Bạn có thể có các phương thức tĩnh và không tĩnh có cùng tên, nhưng các tham số khác nhau tuân theo cùng các quy tắc như quá tải phương thức, chúng không thể có cùng một chữ ký.

+17

Tôi thấy logic của câu trả lời này thiếu sót. Tôi không thấy lý do tại sao C# không thể thực hiện định hướng bằng cách yêu cầu "điều này". token để gọi phương thức cá thể trong tình huống này. Thêm vào đó, andasa hiển thị một cách mà các phương thức tĩnh và instance có thể có cùng tên. – mheyman

+3

Đúng, họ có thể làm một số loại kiểm tra mà sẽ chọn phương pháp tĩnh theo mặc định nếu có va chạm, và yêu cầu này. để truy cập các phương thức thể hiện. Tất nhiên sẽ trở nên phức tạp khi xử lý các thuộc tính tĩnh, vì trong phạm vi của một phương thức nếu các tham số của bạn được đặt tên giống như một thuộc tính tĩnh/instance của bạn thì bạn phải sử dụng tên lớp để chỉ định phiên bản tĩnh, để chỉ định phiên bản cá thể và nếu không có gì, hãy truy cập tham số. Âm thanh như một cách tuyệt vời để có được rất nhiều khó khăn để tìm lỗi cho tôi. – ckramer

+2

Tôi nghĩ rằng tất cả các cuộc gọi từ một phạm vi không tĩnh nên được thực hiện theo phương pháp không tĩnh theo mặc định. Nếu bạn muốn toàn cầu thì bạn nên yêu cầu nó bằng cách đặt trước tên lớp. –

11

Bạn có thể gọi các phương thức tĩnh từ phương pháp dụ mà không cần phải ghi rõ tên loại:

class Foo 
{ 
    static void Bar() 
    { 
    } 

    void Fizz() 
    { 
     Bar(); 
    } 
} 

... do đó, nó có ý nghĩa rằng bạn sẽ không được phép để có một phương pháp tĩnh và một phương pháp dụ với cùng một chữ ký.

Bạn đang cố gắng làm gì? Thật khó để đề xuất một giải pháp thay thế mà không biết chi tiết cụ thể. Tôi chỉ cần đổi tên một trong những phương pháp.

0

Bạn có thể có phương thức tĩnh và ví dụ có cùng tên, miễn là khai báo của chúng khác nhau về số lượng hoặc loại thông số. Đó là quy tắc tương tự về cách bạn có thể có hai phương thức thể hiện có cùng tên trong một lớp. Mặc dù về mặt kỹ thuật, trong trường hợp phương pháp tĩnh so với ví dụ, chúng đã khác nhau bởi sự có mặt của tham số này trong phương thức thể hiện, sự khác biệt đó là không đủ để trình biên dịch xác định xem bạn muốn gọi điện.

Cập nhật: Tôi đã nhầm lẫn. Giá trị trả lại không đủ để có chữ ký khác nhau.

+0

Sai: miễn là khác nhau về số lượng và/hoặc loại thông số. Các kiểu trả về không quá tải. – asterite

+0

[thở dài] vâng, bạn đang phải ... –

36

Thực ra, có một cách để thực hiện điều này bằng cách triển khai một giao diện rõ ràng. Nó không phải là một giải pháp hoàn hảo nhưng nó có thể hoạt động trong một số trường hợp.

interface IFoo 
{ 
    void Bar(); 
} 

class Foo : IFoo 
{ 
    static void Bar() 
    { 
    } 

    void IFoo.Bar() 
    { 
     Bar(); 
    } 
} 

Đôi khi tôi gặp phải tình huống này khi tôi tạo các lớp trình bao bọc cho các cuộc gọi P/Invoke.

+0

Lý do chính xác của tôi để thực hiện điều này là P/Gọi điện. Cảm ơn :) – Asheh

+0

Chỉ cần khắc phục điều đó, @Kamarey. Triển khai giao diện rõ ràng phải không có công cụ sửa đổi truy cập, nó luôn được công khai. – Palec

-1

OK. Gốc của vấn đề này là C# không nên cho phép bạn gọi một phương thức tĩnh từ một phương thức thể hiện mà không chỉ định tên kiểu.

Các ngôn ngữ OO đầy đủ khác (như Smalltalk) không cho phép điều này và cũng gây nhầm lẫn cho những người hiểu đối tượng. Sự tách biệt giữa phía cá thể và lớp (hoặc tĩnh) là rất quan trọng và có một ngôn ngữ thúc đẩy sự nhầm lẫn trong các chi tiết đó là ........ không phải là một ý tưởng tốt .... nhưng điển hình của các loại công cụ chúng tôi mong đợi từ MS.

Adrian

+0

Bài đăng của bạn không trả lời câu hỏi. Vui lòng xem xét thêm câu trả lời cụ thể cho câu hỏi hoặc thêm nhận xét để giải thích câu hỏi. –

+1

Tôi hiểu các downvotes vì ​​nó không trả lời câu hỏi, nhưng điều này thực sự là nguyên nhân của vấn đề. Nó có ý nghĩa hơn với một nhà phát triển để xem tên lớp trước một phương thức tĩnh như một chỉ báo nháy mắt "Có, đây là phương pháp tĩnh, thuộc tính, trường" vv ... – Brandon

+1

Ba năm sau, nhưng tôi muốn nói rằng tôi đánh giá cao những điểm @Adrian được thực hiện, chỉ cần không phải là vài câu nói pejorative hoàn toàn off-base, đặc biệt: "C# không nên để bạn gọi", "nhưng điển hình của các loại công cụ chúng tôi mong đợi từ MS." Điểm đầu tiên mặc dù là một ý kiến ​​FINE để giữ, nhưng không nên được nêu như một vấn đề của thực tế. –

3

C# không được thiết kế tốt khi nói đến này ...

Trong khi đó là sự thật mà bạn có thể muốn toàn cầu hay không toàn cầu, cần chọn một cách mặc định, và nếu bạn muốn người kia sau đó bạn chỉ đơn giản là hội đủ điều kiện nó hơn.

class Logger { 
    public static Logger instance; 

    public static void Log(string message) { 
     instance.Log(message); // currently the compiler thinks this is ambiguous, but really its not at all. Clearly we want the non-static method 
    } 

    public void Log(string message) { 

    } 

    public void DoStuff() { 
     Log("doing instance stuff"); // this could be ambiguous, but in my opinion it should default to a call to this.Log() 
     Logger.Log("doing global stuff"); // if you want the global qualify it explicitly 
    } 
} 
Các vấn đề liên quan