2010-02-27 48 views
19

như thế nào C#, hoặc ngôn ngữ khác cho rằng vấn đề, xử lý cấp phát bộ nhớ (và bộ nhớ de-phân bổ) giữa hai kịch bản sau đây:C dụ # lớp học với phương pháp tĩnh vs sử dụng bộ nhớ lớp tĩnh

1.) Một phương pháp trên một lớp tĩnh được gọi.

public Program { 
    Foo foo = Loader.load(); 
} 

public static Loader { 
    public static Foo load() { 
     return new Foo(); 
    } 
} 

2.) Phương thức được gọi trên một cá thể, sau đó nằm ngoài phạm vi.

public Program { 
    Foo foo = new Loader().load(); 
} 

public Loader { 
    public Foo load() { 
     return new Foo(); 
    } 
} 

Tôi cho rằng lớp tĩnh được tải và vẫn còn trong bộ nhớ; trong khi dụ lớp không chống lại việc thu gom rác khi giải trí của C#. Có bất kỳ ưu nhược điểm nào cho hai mô hình này không? Có bao giờ một thời gian khi bạn có một lớp mà không bao giờ cần phải được khởi tạo (tức là một số loại bộ nạp tài nguyên hoặc nhà máy), nhưng bạn vẫn sử dụng phương pháp thứ hai để tận dụng bộ sưu tập rác?

Phần quan trọng trong câu hỏi của tôi là liệu mô hình đầu tiên hay không, trong khi khái niệm chính xác trong một số trường hợp, có thể bị giữ trên bộ nhớ không cần thiết.

+3

Ví dụ thứ 2 có vẻ không chính xác với tôi. Việc gọi một phương thức tĩnh yêu cầu một phương thức tiền tố với tên lớp. ví dụ. 'Loader.Load()' & ** not ** 'new Loader(). Load()' – shahkalpesh

+0

Bạn nói đúng, Shah - bạn không cần một cá thể để gọi một phương thức tĩnh. Đó là kinda điểm :) –

+0

ah, các bạn là đúng, cảm ơn, tôi đã reworded nó để có được ở thịt của câu hỏi tôi đã cố gắng để yêu cầu. – jtb

Trả lời

8

Ví dụ thứ hai của bạn không hoạt động, vì vậy hãy khám phá các tùy chọn thực tế:

1.) Phương thức trên lớp tĩnh được gọi.

public Program { 
    Foo foo = Loader.Load(); 
} 

public static Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

2.) Phương thức tĩnh trong lớp không tĩnh được gọi.

public Program { 
    Foo foo = Loader.Load(); 
} 

public Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

3.) Một phương pháp dụ được gọi vào một thể hiện

public Program { 
    Foo foo = new Loader().Load(); 
} 

public Loader { 
    public Foo Load() { 
     return new Foo(); 
    } 
} 

Việc đầu tiên hai đều giống nhau. Gọi một phương thức tĩnh là như nhau bất kể lớp đó có tĩnh hay không.

Tùy chọn thứ ba sẽ tạo một phiên bản của lớp trên heap. Vì lớp không có các thành viên dữ liệu, nó sẽ chỉ là 16 byte. Nó sẽ được thu thập rác cuối cùng, nhưng do kích thước nhỏ nó không quan trọng nhiều khi điều đó xảy ra.

Gọi phương thức thể hiện cũng hơi khác so với phương pháp tĩnh. Tham chiếu đến cá thể lớp được gửi cùng, bạn có thể truy cập thông qua từ khóa this. Nó tạo ra sự khác biệt nhỏ trong trường hợp này vì không có dữ liệu thực trong đối tượng truy cập.

+0

Dấu chân bộ nhớ của chương trình C# có thay đổi khi một thể hiện của một đối tượng là rác được thu thập (ngoài dữ liệu trường thể hiện), có bao giờ loại bỏ thông tin Loại đã từng xảy ra không? Để đặt nó một cách thông tục, C# sẽ thực hiện bất kỳ tối ưu nào như "Ồ, không có lớp nào trong số các lớp này hiện có trường hợp, tôi không cần chúng nữa, tôi sẽ xóa dữ liệu Kiểu thô khỏi chương trình và lưu một số bộ nhớ "? – jtb

+0

@jtb: Không, với kiến ​​thức của tôi .NET sẽ không dỡ bỏ một assembly đã từng được nạp. – Guffa

+0

@jtb GC sẽ chỉ miễn phí bộ nhớ được thực hiện bởi lớp học của bạn chỉ khi nó không có tài liệu tham khảo/xử lý vv và chỉ khi tài nguyên bộ nhớ hệ điều hành là khan hiếm. –

1

Phương thức tĩnh, trường, thuộc tính hoặc sự kiện có thể gọi trên lớp ngay cả khi không có cá thể nào của lớp được tạo. nó có phạm vi để loại:

http://msdn.microsoft.com/en-us/library/79b3xss3(VS.80).aspx

Vì vậy, trong ý nghĩa đó phương pháp tĩnh của bạn cũng giống như nó sẽ nếu bạn sử dụng nó từ bên trong một cá thể của lớp cư xử.

+0

yeah, sry, ví dụ của tôi bị viết kém để minh họa cho câu hỏi của tôi. Tôi không biết đây có phải là nghi thức SO đúng đắn không, bởi vì bạn đúng, nhưng tôi sẽ phải thuật lại câu hỏi của tôi một chút để hỏi câu hỏi mà tôi thực sự muốn. – jtb

+0

Cho rằng một thành viên tĩnh được phạm vi theo loại, tôi không nghĩ rằng việc sử dụng bộ nhớ sẽ thay đổi chỉ vì bạn gọi nó trong một thể hiện của loại đó. –

1

Biểu mẫu thứ hai tạo đối tượng Loader tạm thời (rất rẻ). Bạn sẽ luôn phải tải lớp Loader, bất kể bạn chọn phương pháp nào.

Có rất ít hiệu suất (tiết kiệm bộ nhớ) để đạt được ở đây. Bạn thường sẽ chọn cho một thành viên tĩnh trong một lớp tĩnh nếu không có 'trạng thái' cần thiết bên ngoài các phương thức vars cục bộ.

+0

@Henk: Ví dụ thứ 2 sẽ không biên dịch trong C#. đúng? – shahkalpesh

+0

@Shah Nó sẽ biên dịch. lưu ý ví dụ thứ 2 không gọi phương thức tĩnh! Nó đang gọi một phương thức công khai bình thường trong một thể hiện mà sau đó là rác thu thập được vì nó không bao giờ được thiết lập lại. –

+0

vâng, mọi người đang bối rối vì bài đăng gốc của tôi có phương pháp trong ví dụ thứ hai được đánh dấu là tĩnh, tôi đã chỉnh sửa nó. – jtb

0

tôi không thể tìm thấy bất kỳ nguồn cho điều này, nhưng từ sự hiểu biết của tôi về lập trình, khi bạn refernce một lớp (không tĩnh), đó là cấu trúc được nạp vào bộ nhớ

Tạo một thể hiện của một lớp học chỉ để gọi một phương thức , sẽ lãng phí rất nhiều sức mạnh xử lý (do tạo ra một thể hiện, gán bộ nhớ, và thu gom rác).

Thay vì giữ định nghĩa, và sau đó trên đầu trang của nó, một ví dụ. Tại sao không chỉ giữ định nghĩa (tĩnh).

Miễn là bạn không lưu trữ bất kỳ dữ liệu nào trong các biến tĩnh, phương pháp tĩnh của bạn sẽ chiếm cùng một lượng bộ nhớ như định nghĩa phương thức tĩnh của bạn. Nhưng bằng cách sử dụng một phương thức tĩnh, chỉ có phương thức sẽ được giữ trong bộ nhớ và sẵn sàng để được gọi bất cứ khi nào bạn cần mà không cần tạo các cá thể. Trong trường hợp, nếu phương thức này không tĩnh, nó sẽ cần phải được khởi tạo (sử dụng bộ nhớ và sức mạnh xử lý) và thu gom rác (giải phóng bộ nhớ và sử dụng cpu) do đó nó chắc chắn là tốt hơn khi sử dụng một thành viên tĩnh. Đó là những gì họ đang có.

+0

Khi một lớp tĩnh được tham chiếu đầu tiên, sự hiểu biết của tôi là C# chạy bộ khởi tạo tĩnh, nạp các trường tĩnh vào bộ nhớ và nạp dữ liệu Kiểu (cấu trúc lớp) vào bộ nhớ, giữ nó trong suốt thời gian chạy chương trình. Khi một thể hiện của một lớp được tạo, hàm tạo được xử lý, bộ nhớ được cấp phát cho các trường thể hiện và dữ liệu Kiểu được nạp vào bộ nhớ (nếu nó chưa có). Tuy nhiên, khi một cá thể của một lớp rời khỏi phạm vi, dữ liệu của nó cuối cùng được thừa kế với ête, nhưng dữ liệu Kiểu có được phát hành không? – jtb

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