2010-09-13 43 views
11

Tôi đã thường xuyên suy nghĩ về điều này ... nó có thể là một câu hỏi ngốc nghếch nhưng ở đây đi.Tôi có nên luôn làm cho phương pháp của mình tĩnh khi có thể không?

Nói rằng tôi có lớp học này:

public class SomeClass 
{ 
    public int AProperty { get; set; } 

    public void SomeMethod() 
    { 
     DoStuff(AProperty); 
    } 
} 

Có lợi thế nào để làm điều này:

public class SomeClass 
{ 
    public int AProperty { get; set; } 

    public static void SomeMethod(int arg) 
    { 
     DoStuff(arg); 
    } 
} 

Ưu điểm duy nhất mà là rõ ràng là bây giờ tôi có thể truy cập trực tiếp SomeMethod.

Vì vậy, có thực tiễn tốt để làm cho các loại phương pháp này tĩnh, nơi một phép tái cấu trúc nhỏ sẽ cho phép hoặc lãng phí thời gian của tôi không?

EDIT: tôi quên đề cập đến (và comment ShellShock của nhắc nhở tôi) rằng lý do tôi hỏi là tôi sử dụng ReSharper và nó luôn luôn làm cho ý kiến ​​cho rằng 'Phương pháp X có thể được thực hiện tĩnh' và vân vân ...

+0

có thể trùng lặp của [Phương pháp tĩnh so với phương pháp không tĩnh] (http://stackoverflow.com/questions/1184701/static-vs-non-static-method) –

+0

Nếu phương pháp không yêu cầu dữ liệu cụ thể về cá thể bạn có thể làm cho nó tĩnh. – halfdan

+0

Tôi biết halfdan, nhưng tôi hỏi - Tôi có nên không? – Nobody

Trả lời

15

Tĩnh không phải là điều xấu. Tĩnh là tà ác nếu được sử dụng không chính xác, giống như nhiều phần trong bộ công cụ lập trình của chúng tôi.

Tĩnh có thể rất thuận lợi. Như the accepted answer here chỉ ra, tĩnh có thể có một cải thiện tốc độ tiềm năng.

Như một quy tắc chung nếu phương pháp không sử dụng và các trường của lớp thì đây là thời điểm tốt để đánh giá chức năng của nó, tuy nhiên cuối cùng các phương thức tiện ích có thể được gọi mà không khởi tạo một đối tượng có thể hữu ích. Ví dụ: các lớp học DirectoryInformationFileInformation chứa các phương pháp tĩnh hữu ích.

Sửa

Cảm thấy bắt buộc phải chỉ ra rằng nó làm cho chế giễu khó khăn hơn rất nhiều, nhưng nó vẫn còn chắc chắn kiểm chứng.

Chỉ có nghĩa là bạn cần phải suy nghĩ kỹ về trong đó phương pháp tĩnh đi, để bạn luôn có thể kiểm tra chúng mà không cần phải dựa vào mô hình/sơ khai.(ví dụ: không đặt chúng trên DTO của bạn yêu cầu kết nối liên tục với cơ sở dữ liệu).

1

No. Static is evil. Nó kết hợp chặt chẽ người gọi đến lớp được sử dụng và makes it hard to test.

+1

Công cụ Phân tích Mã của Microsoft luôn gợi ý rằng tôi nên tạo các phương thức tĩnh nếu không có sự phụ thuộc cá thể nào. Đây có phải là lời khuyên xấu không? – Polyfun

+0

@ShellShock Có thể. Nếu bạn có nhiều phương pháp như vậy, bạn có thể vi phạm các nguyên tắc OOP. Một phương thức của một đối tượng nên (hầu như) luôn làm việc với dữ liệu liên quan đến đối tượng. –

+0

@dark_charlie: Vì vậy, những gì bạn nói là nếu bạn có thể có một phương thức tĩnh, bạn nên cấu trúc lại để đưa nó ra trong một lớp tiện ích tĩnh thay vào đó? Điều gì sẽ xảy ra nếu phương pháp được liên kết một cách hợp lý với lớp học, nhưng về mặt kỹ thuật không sử dụng bất kỳ thành viên nào? – awe

1

Tôi nghĩ nó sẽ phụ thuộc vào cách bạn muốn sử dụng các phương pháp. Sử dụng một phương pháp tĩnh là okay nếu nó được sử dụng như một phương pháp phổ biến trong một vài trường hợp của lớp.

Vì lợi ích của một ví dụ, giả sử bạn có một lớp chuỗi và hai chuỗi A và B. Để so sánh A và B, bạn có thể có phương thức A.CompareTo (B) hoặc String.Compare (A, B) phương pháp.

Vui lòng sửa tôi nếu tôi sai.

+0

Tôi nghĩ 'XDocument.Parse' sẽ là một ví dụ tốt hơn. Sẽ không có nhiều điểm trong việc tạo ra một XDocument chỉ để sử dụng phương thức phân tích cú pháp của nó để tạo ra XDocument mà bạn thực sự muốn. –

2

Phương thức tĩnh có ý nghĩa, nếu bạn có thể gọi chúng mà không cần tạo đối tượng của lớp trước đó. Trong Java, ví dụ, Math-Class chỉ chứa các phương thức tĩnh, bởi vì nó sẽ không có ý nghĩa nhiều để instanciate một Math-Class chỉ để thực hiện các phép toán trên các đối tượng khác.

Hầu hết thời gian tốt hơn là tránh phương pháp tĩnh. Bạn nên làm quen với lập trình hướng đối tượng - có rất nhiều tài nguyên tốt, giải thích tất cả các khái niệm như phương pháp tĩnh, v.v.

2

Tôi sẽ cố gắng trả lời câu hỏi cụ thể của bạn liên quan đến mẫu mã bạn đã cung cấp.

Nếu SomeMethod chỉ hữu ích trong lớp được khai báo, tôi sẽ tránh chuyển đổi tĩnh và để nó làm phương pháp thể hiện.

Nếu SomeMethod hữu ích bên ngoài lớp học, hãy đưa nó ra khỏi lớp học. Điều này có thể là một phương thức tĩnh trong một lớp tiện ích tĩnh ở đâu đó. Để làm cho nó có thể kiểm tra, hãy đảm bảo rằng tất cả các phụ thuộc của nó được truyền vào nó làm đối số. Nếu nó có nhiều phụ thuộc, bạn có thể muốn xem lại thiết kế và tìm ra chính xác những gì nó được cho là đang làm - nó có thể tốt hơn như một phương thức thể hiện trong một trong các lớp mà bạn đang truyền vào nó.

Một số người cho rằng tĩnh là điều xấu. Điều này thường là do những cạm bẫy mà trạng thái tĩnh có thể thay đổi được cung cấp, trong đó các biến treo xung quanh từ điểm mà một hàm tạo tĩnh được gọi là giọt nước mắt của miền ứng dụng, thay đổi ở giữa. Mã lệ thuộc vào trạng thái đó có thể hoạt động không thể đoán trước và thử nghiệm có thể trở nên khủng khiếp. Tuy nhiên, hoàn toàn không có gì sai với một phương thức tĩnh không tham chiếu trạng thái tĩnh có thể thay đổi được.

Đối với một (rất đơn giản) ví dụ nơi một tĩnh là ác, nhưng có thể được chuyển đổi sang một phiên bản không-ác, hãy tưởng tượng một hàm để tính toán tuổi của một ai đó:

static TimeSpan CalcAge(DateTime dob) { return DateTime.Now - dob; } 

Có phải đó là kiểm chứng? Câu trả lời là không. Nó dựa trên trạng thái tĩnh biến động ồ ạt là DateTime.Now. Bạn không được đảm bảo cùng một đầu ra cho cùng một đầu vào mỗi lần. Để làm cho bài kiểm tra trở nên thân thiện hơn:

static TimeSpan CalcAge(DateTime dob, DateTime now) { return now - dob; } 

Bây giờ, tất cả các giá trị mà hàm dựa vào đều được chuyển vào và hoàn toàn có thể kiểm tra được. Cùng một đầu vào sẽ đưa bạn cùng một đầu ra.

+0

Bạn nói rằng nếu phương pháp chỉ hữu ích trong lớp, thì đừng làm cho nó tĩnh. Không phải nó cũng có hiệu suất đạt được bằng cách làm cho một phương pháp tĩnh? Hoặc người nào khác là điểm có phương pháp 'private static' (có thể, và thực sự được gợi ý bởi ReSharper)? – awe

+0

@awe - đúng là gọi phương thức tĩnh sẽ nhanh hơn. Tuy nhiên, tôi nghĩ rằng ví dụ cụ thể này gọi 'someClassInstance.SomeMethod()' là tốt hơn 'SomeClass.SomeMethod (someClassInstance.AProperty)'. Tôi không nghĩ rằng các refactor đề xuất trong câu hỏi là điều tốt nhất để làm - trong nhiều trường hợp khác nó được. ReSharper có đề xuất refactor cho ví dụ trên không? Nó sẽ làm tôi ngạc nhiên nếu nó đã làm như phương pháp truy cập một tài sản dụ. Bạn có thể đi toàn bộ con heo và viết 'static SomeMethod (SomeClass this)' cho * tất cả * các phương thức cá thể không ảo của bạn nếu bạn muốn. –

+0

Tôi đồng ý với bạn trong trường hợp này, nhưng bạn đã xây dựng nó theo cách không rõ ràng với tôi. Ý tôi là trong ví dụ mà phương thức chỉ hữu dụng trong ngữ cảnh của lớp, nhưng về mặt kỹ thuật thì không sử dụng bất kỳ thành viên nào trong lớp. Phương thức này thực sự chỉ là một số chức năng tiện ích, nhưng không có mã nào khác ngoài lớp cần chức năng này. Resharper đề nghị refactor nếu phương thức của bạn không sử dụng bất kỳ thành viên hoặc phương thức không tĩnh nào trong lớp của bạn. Tôi nhận thấy điều này trong một phương pháp riêng tư mà tôi tạo ra mà ReSharper đề xuất để làm cho tĩnh. – awe

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