2011-02-08 22 views
11

Tôi có một đối tượng được quản lý trong một hội đồng C++/CLI. Là C++/CLI, nó thực hiện mẫu dùng một lần thông qua "destructor" của nó (vâng, tôi biết nó không giống như một tiêu chuẩn C++ destructor). Từ C++/CLI, tôi chỉ đơn giản là delete đối tượng. Tuy nhiên, tôi đang sử dụng đối tượng này như là một biến thành viên trong một lớp C#.Làm thế nào tôi có thể định nghĩa một cách xác định đối tượng C++/CLI được quản lý từ C#?

Từ lớp C# của tôi, sau đó, tôi muốn gọi tương đương với phương thức Dispose() trên đối tượng C++/CLI khi tôi kết thúc sử dụng nó. Vì nó là (và phải là) một biến thành viên của lớp, việc sử dụng một khối using() không nằm trong câu hỏi. Theo như tôi có thể nói, không có phương pháp tiếp xúc nào để xử lý trực tiếp, định lượng các tài nguyên từ một ngôn ngữ khác với ngôn ngữ C++/CLI. Làm thế nào tôi có thể thực hiện điều này?

+0

Tôi không hiểu, có gì sai với ['Dispose'] (http://msdn.microsoft.com/en-us/) thư viện/system.idisposable.dispose.aspx) phương pháp? Bạn không thể thực hiện mẫu dùng một lần mà không có nó. –

+1

Lớp C++/CLI không hiển thị phương thức 'Dispose()'. Đó là ngầm định trong cú pháp giống như destructor của C++/CLI (ví dụ 'MyClass'), nhưng khi tham chiếu đối tượng từ C#, bạn không có phương thức' Dispose() 'tiếp xúc, gần như tôi có thể nói. – JimEvans

Trả lời

9

Cú pháp giống như hủy diệt C++/CLI tự động triển khai IDisposable, nhưng nó theo cách tương tự như của C# 'explicit interface implementation. Điều này có nghĩa bạn sẽ phải đúc để IDisposable để truy cập Dispose phương pháp:

((IDisposable)obj).Dispose(); 
+3

Đừng thử ở nhà: bạn có thể sử dụng câu lệnh trống 'using' thay vì gọi phương thức Dispose:' using (obj); '. Nhưng hãy suy nghĩ về những đứa trẻ. –

+0

Tôi chấp nhận điều này như là câu trả lời, mặc dù nó thực sự không. Câu hỏi chính nó không phải là một câu hỏi hợp lệ; vấn đề là trong mã C++/CLI của tôi. Tôi đã sử dụng thực hiện một lớp trừu tượng, nhưng trả về lớp cơ sở trừu tượng từ phương thức factory, và lớp cơ sở không thực hiện một destructor, và do đó không có phương thức Dispose() tiếp xúc. – JimEvans

-2

Bạn không thể. Ít nhất, không phải từ C#. Hãy để người thu gom rác thực hiện công việc của mình.

+0

Chắc chắn bạn có thể. C# thậm chí có một từ khóa cho nó. –

+0

* Xác định? * Từ khóa nào? (Nghiêm túc. Tôi muốn biết.) –

+1

Câu lệnh 'using' được tạo ra để cho phép loại bỏ các nguồn tài nguyên xác định. –

9

Nó không phải là quá rõ ràng trong C++/CLI nhưng nó hoạt động chính xác cách nó trong C#. Bạn có thể nhìn thấy nó khi bạn nhìn vào lớp với Object Browser. Hoặc một trình biên dịch ngược như ildasm.exe, cách tốt nhất để xem nó làm gì.

Khi bạn viết trình phá hủy, trình biên dịch C++/CLI tự động tạo một nhóm mã. Nó thực hiện mô hình dùng một lần, lớp của bạn sẽ tự động triển khai IDisposable, mặc dù bạn không khai báo nó theo cách đó. Và bạn có được một phương thức Dispose() công khai, một phương thức Dispose (bool) được bảo vệ và một cuộc gọi tự động tới GC :: SuppressFinalize().

Bạn sử dụng delete trong C++/CLI để gọi một cách rõ ràng, trình biên dịch sẽ phát ra cuộc gọi Dispose(). Và bạn nhận được tương đương với RAII trong C++/CLI bằng cách sử dụng ngữ nghĩa ngăn xếp, trình biên dịch tự động phát ra cuộc gọi Dispose ở cuối khối phạm vi. Cú pháp và hành vi quen thuộc với các lập trình viên C++.

Bạn làm chính xác điều bạn sẽ làm trong C# nếu lớp học đã được viết bằng C#. Bạn gọi Dispose() để gọi một cách rõ ràng, bạn sử dụng câu lệnh using để gọi nó một cách ngầm định một cách ngoại lệ.

Các quy tắc tương tự được áp dụng khác, bạn chỉ cần cần trình phá hủy khi bạn cần phát hành một thứ không được quản lý bộ nhớ. Hầu như luôn luôn là một đối tượng bản địa, cái mà bạn đã cấp phát trong hàm tạo. Hãy xem xét rằng nó có thể không có giá trị bận tâm nếu đối tượng không được quản lý là nhỏ và rằng GC :: AddMemoryPressure() là một thay thế rất phong nha. Tuy nhiên, bạn phải triển khai finalizer (!ClassName()) trong lớp trình bao bọc như vậy. Bạn không thể ép buộc mã máy khách bên ngoài gọi Dispose(), làm như vậy là tùy chọn và nó thường bị lãng quên. Bạn không muốn một sự giám sát như vậy gây ra một rò rỉ bộ nhớ không được quản lý, finalizer đảm bảo rằng nó vẫn được phát hành. Thông thường, cách đơn giản nhất để viết trình phá hủy là gọi rõ ràng trình kết thúc (this->!ClassName();)

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