2010-07-30 37 views
7

gì (nếu có) vừa là điểm mạnh hay nhược điểm (hiệu suất, thực hành mã hóa tốt, thu gom rác thải, vv) của cách gọi một phương pháp không tĩnh của một lớp theo cách dưới đây:Gọi phương pháp không tĩnh của một lớp

new ClassA().MethodA(param1, param2); 

như chống lại cách hơn "truyền thống" của

ClassA classA = new ClassA(); 
classA.MethodA(param1, param2); 

suy nghĩ Bất kỳ sẽ được đánh giá rất nhiều.

+0

Lớp học có tạo bất kỳ tài nguyên không được quản lý nào hoặc triển khai IDisposable không? – SwDevMan81

Trả lời

10

Mã hóa
Đối với thực hành mã hóa, tùy chọn thứ hai tốt hơn, nơi đối tượng được lưu trữ trong biến trước tiên. Lý do làm cho nó tốt hơn là bạn có thể đặt tên đối tượng theo ngữ cảnh mà nó được sử dụng. Ví dụ:

var pendingUserForRegistration = new User(); 

Performance
Đối với hiệu suất, tùy chọn đầu tiên có thể tốt hơn một chút, vì nó sử dụng các đối tượng trực tiếp từ ngăn xếp và bỏ qua việc lưu trữ các đối tượng trong một biến địa phương .Nó có thể được nhìn thấy từ IL của phương pháp:

IL của đầu tiên:

.maxstack 8 
L_0000: nop 
L_0001: newobj instance void NS.ClassA::.ctor() 
L_0006: call instance void MS.ClassA::M() 
L_000b: nop 
L_000c: ret 

IL của thứ hai:

.maxstack 1 
.locals init (
    [0] class NS.ClassA c) 
L_0000: nop 
L_0001: newobj instance void NS.ClassA::.ctor() 
L_0006: stloc.0 
L_0007: ldloc.0 
L_0008: callvirt instance void NS.ClassA::M() 
L_000d: nop 
L_000e: ret 

này thường là một buổi biểu diễn trên không nhỏ, đó là khó tìm ra một trường hợp nó sẽ giải quyết một vấn đề hiệu năng thực sự.


Tóm lại
Kể từ khi bảo trì của tăng mã ở đây là lớn hơn so với hiệu suất đạt được nó ưa thích để lưu trữ các đối tượng trong một biến với tên có ý nghĩa.

+1

Cảm ơn Elisha. Câu trả lời chi tiết tuyệt vời. Chính xác những gì tôi cần. –

+0

Ngoài ra, gợi ý trong nhận xét của @ SwDevMan81 về câu hỏi - nếu đối tượng bạn đang sử dụng là một lần bạn muốn đặt nó vào một biến để sau này bạn có thể vứt bỏ nó một cách sạch sẽ; thực hiện nó theo cách đầu tiên để dọn sạch wot đối tượng finalizer của đối tượng, có thể (ví dụ) để các kết nối mở. – JohnLBevan

3

Nó sẽ không tạo ra bất kỳ sự khác biệt nào cả. Chỉ trong tình huống này, một phương pháp tĩnh có lẽ sẽ thích hợp hơn.

+0

Tôi đồng ý, tiếc là ảnh hưởng của tôi không mở rộng để sửa đổi lớp đó :). Cũng trở thành một chút khó khăn để quản lý đa luồng –

0

Nói chung, tôi sử dụng các phương pháp tĩnh khi tôi không cần lớp học để "biết" bất cứ điều gì; Tôi sử dụng các phương thức thể hiện khi lớp cần biết về chính nó và trạng thái riêng của nó.

Nhiều hơn hoặc ít hơn.

1

Nếu bạn không sử dụng ClassA cho bất kỳ điều gì khác, hơn new ClassA().MethodA(param1, param2); là OK. Nếu không, bạn nên sử dụng bản thuyết trình truyền thống hơn ClassA classA = new ClassA();

+0

Làm cho tinh thần. Cảm ơn rất nhiều vì phản hồi nhanh chóng. –

0

Tôi tự hỏi tại sao bạn muốn thực hiện điều này tại trang web gọi điện. Nếu bạn không thể đi xung quanh nó, nó có thể là tốt hơn để bọc new ClassA().MethodA(a,b) trong một phương pháp tĩnh để tránh tiếng ồn mã tại trang web cuộc gọi.

+0

Hmmm ... sau đó trở nên khó khăn để quản lý đa luồng –

0

Chúng giống hệt nhau. Cách tiếp cận đầu tiên có nghĩa là một ít dòng mã hơn. Cách tiếp cận thứ hai là đẹp hơn nếu ai đó cần sửa đổi mã để bắt đầu gọi MethodB.

+0

Làm cho ý nghĩa về điểm thứ hai. Có lẽ trình biên dịch sẽ giải quyết cả hai cách giống nhau. Cảm ơn bạn đã phản hồi nhanh như vậy –

1

Tôi không thể thấy bất kỳ sự khác biệt nào giữa chúng. Tuy nhiên, nếu ClassA thực hiện IDisposable cả hai đều là một ý tưởng tồi.

+0

Cảm ơn bạn đã phản hồi nhanh. Nếu ClassA triển khai IDisposable, các repurcussions là gì? –

+0

Nếu 'ClassA' triển khai' IDisposable', bạn nên gọi phương thức 'Dispose' khi cá thể không còn cần thiết, hoặc bằng tay hoặc thông qua câu lệnh' using'. Không làm như vậy có thể làm cho mã bị rò rỉ tài nguyên không được quản lý (tùy thuộc vào những gì 'ClassA' làm). –

+0

Cảm ơn rất nhiều, Fredrik. Tôi đánh giá cao việc làm rõ. –

2

Không có sự khác biệt ở mặt sau. Trong CIL nó sẽ tạo ra một đối tượng ClassA, sau đó gọi phương thức. Cả hai phần của mã dịch sang cùng một CIL, do đó không có sự khác biệt hiệu suất nào cả.

+0

Cảm ơn rất nhiều Scott, đó là những gì tôi đã tự hỏi. –

1

Cả hai đều giống hệt nhau. Trong thực tế, có một cơ hội tốt trình biên dịch sẽ tạo ra IL giống nhau cho mỗi.

Phương pháp truyền thống này là một lợi thế trong gỡ lỗi, nếu bạn chắc chắn nếu một vấn đề trong ctor hoặc trong MethodA; hoặc nếu MethodA thay đổi đối tượng, và bạn cần kiểm tra nó.

+0

Gỡ lỗi là một điểm tuyệt vời. Cảm ơn James –

0

Cách tiếp cận đầu tiên của bạn cần khởi tạo một thể hiện của ClassA (ngoài việc tải định nghĩa lớp vào bộ nhớ nếu lớp đó chưa bao giờ được sử dụng cho đến nay). Cách tiếp cận thứ hai tránh sự khởi tạo đối tượng bổ sung này và bộ sưu tập rác sau đây của lớp.

Nếu điều này xảy ra theo thời gian và không phải hàng triệu lần, tôi sẽ không bận tâm. Tuy nhiên, nó sẽ là một thiết kế sạch hơn để thực hiện phương thức tĩnh nếu bạn không cần truy cập vào bất kỳ phương thức hoặc thuộc tính thể hiện lớp nào.

Có một cách tiếp cận hơi khác đôi khi được sử dụng: Giả sử ClassA cần một đối số trong hàm khởi tạo của nó có thể khởi tạo trường riêng hoặc thuộc tính sẽ được sử dụng theo phương thức của bạn. Trong trường hợp này, cách tiếp cận đầu tiên là phải:

new ClassA(param0).MethodA(param1, param2); 

Nhưng - ngay cả khi đó, phương pháp chỉ có thể được định nghĩa lại để tham số bổ sung.

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