Các lớp so với các mô-đun trong VB.NET


157

Được coi là một cách thực hành có thể chấp nhận để sử dụng Mô-đun thay vì Lớp có chức năng thành viên được chia sẻ trong VB.NET?

Tôi có xu hướng tránh các Mô-đun, vì chúng cảm thấy như phần còn lại từ Visual Basic 6.0 và dường như không thực sự phù hợp nữa. Mặt khác, dường như không có nhiều khác biệt giữa việc sử dụng Mô-đun và Lớp chỉ có các thành viên được chia sẻ. Không phải lúc nào tôi cũng thực sự cần nhiều thứ, nhưng đôi khi có những tình huống họ đưa ra một giải pháp đơn giản.

Tôi tò mò muốn biết liệu bạn có ý kiến ​​hay sở thích nào theo cách này hay cách khác.


10
Một điều thú vị về các mô-đun là theo mặc định, các phương thức và hàm được khai báo bên trong có mức bảo vệ của mô-đun, điều đó có nghĩa là bạn có thể vô tình làm cho các phương thức có sẵn nếu bạn quên thêm rõ ràng Privatevòng loại. Trong một lớp, mức bảo vệ mặc định là riêng tư, có thể là hành vi khó hiểu trừ khi bạn biết về nó.
yu_ominae

Câu trả lời:


207

Modules là đối tác VB với staticcác lớp C # . Khi lớp của bạn được thiết kế chỉ dành cho các hàm trợ giúp và phương thức mở rộng và bạn không muốn cho phép kế thừakhởi tạo , bạn sử dụng một Module.

Nhân tiện, sử dụng Modulekhông thực sự chủ quan và nó không bị phản đối . Thật vậy, bạn phải sử dụng Modulekhi nó thích hợp. .NET Framework tự thực hiện nhiều lần ( System.Linq.Enumerableví dụ). Để khai báo một phương thức mở rộng, bắt buộc phải sử dụng Modules.


7
Hoàn toàn đúng, mặc dù tôi có thể sử dụng một hàm tạo riêng để ngăn chặn việc khởi tạo và công cụ sửa đổi NotInheritable. Hơi xấu hơn một Module cũ đơn giản, nhưng có tác dụng tương tự. Cảm ơn con trỏ đã sử dụng các Mô-đun trong Khung; Tôi sẽ xem xét điều đó.
Tom Juergens

8
Dưới mui xe, chúng chỉ được biên dịch thành các lớp có thuộc tính [StandardModule]. Ngoài ra, sử dụng Mô-đun buộc bạn không có những thứ không được chia sẻ, đó là một điều tốt.
Mehrdad Afshari

18
Các mô-đun không giống như các lớp tĩnh trong C #. Các phương thức trong một mô-đun có hiệu quả toàn cầu nếu chúng nằm trong một không gian tên được nhập.
JaredPar

2
@JaredPar: Từ ngữ của tôi có lẽ là xấu. Tôi nên nói VB đối tác với các lớp tĩnh C #. Từ tuyên bố đó, tôi muốn nói rằng việc sử dụng Mô-đun có nghĩa là bạn sẽ viết một lớp tĩnh trong C #.
Mehrdad Afshari

3
@Chiwda Xem msdn.microsoft.com/en-us/l Library / bb384936.aspx : "Các phương thức mở rộng chỉ có thể được khai báo trong các mô-đun."
Mehrdad Afshari

34

Tôi nghĩ rằng đó là một ý tưởng tốt để tiếp tục tránh các mô-đun trừ khi bạn dán chúng vào các không gian tên riêng biệt. Bởi vì trong các phương thức Intellisense trong các mô-đun sẽ hiển thị từ mọi nơi trong không gian tên đó.

Vì vậy, thay vì ModuleName.MyMethod()bạn kết thúc với MyMethod()cửa sổ bật lên ở bất cứ đâu và loại này làm mất hiệu lực đóng gói. (ít nhất là ở cấp độ lập trình).

Đó là lý do tại sao tôi luôn cố gắng tạo Class bằng các phương thức được chia sẻ, có vẻ tốt hơn nhiều.


6
Đồng ý, hiện tại tôi đang làm việc trên một chương trình cũ (có thể là cổng VB6 đến VB.NET 1) với các lớp và mô-đun. Có hàng trăm biến toàn cục, phụ và hàm trong khoảng mười mô-đun khác nhau, và thật khó để tìm ra cái gì bắt nguồn từ đâu và làm thế nào nó được sửa đổi.
yu_ominae

ok cái này rất cũ, nhưng liên quan đến câu hỏi của tôi. Tôi không phải là người VB, nhưng tôi phải làm việc với nó. Tôi đang cố gắng phá vỡ một lớp lớn (> 46.000 dòng) vì IntelliSense / ReSharper chỉ chết. Tôi đã tìm thấy bằng cách sử dụng các Mô-đun và chỉ trích xuất các khối lớn các chức năng vào Mô-đun riêng của chúng dường như hoạt động, nhưng tôi tự hỏi liệu tôi có nên cung cấp cho mỗi mô-đun không gian tên của riêng mình không. Điều đó có cần thiết không? tức là nó sẽ tăng tốc IntelliSense chỉ với các Mô-đun, hoặc Không gian tên sẽ giúp nhiều hơn?
codah

27

Các mô-đun không có nghĩa là không được chấp nhận và được sử dụng nhiều trong ngôn ngữ VB. Chẳng hạn, đó là cách duy nhất để thực hiện một phương thức mở rộng trong VB.Net.

Có một sự khác biệt lớn giữa Mô-đun và Lớp với Thành viên tĩnh. Bất kỳ phương thức nào được xác định trên Mô-đun đều có thể truy cập toàn cầu miễn là Mô-đun có sẵn trong không gian tên hiện tại. Trong thực tế, một Module cho phép bạn xác định các phương thức toàn cầu. Đây là điều mà một lớp chỉ có các thành viên được chia sẻ không thể làm được.

Đây là một ví dụ nhanh mà tôi sử dụng rất nhiều khi viết mã VB xen kẽ với các giao diện COM thô.

Module Interop
  Public Function Succeeded(ByVal hr as Integer) As Boolean
    ...
  End Function

  Public Function Failed(ByVal hr As Integer) As Boolean
    ...
  End Function
End Module

Class SomeClass
  Sub Foo()
    Dim hr = CallSomeHrMethod()
    if Succeeded(hr) then
      ..
    End If
  End Sub
End Class

4
Các phương thức mở rộng ... một tính năng tốt khác tôi luôn có ý định sử dụng, nhưng không bao giờ thực sự có được - tốt, điều này mang lại cho tôi một cơ hội tốt khác. Tôi có một chút về phạm vi toàn cầu, và các phương pháp có sẵn trên toàn cầu chắc chắn có thể thuận tiện, nhưng tôi cảm thấy hơi lo lắng về việc lạm dụng chúng. Ở mức độ nào, tất cả các câu trả lời cho đến nay đều nói với tôi rằng tôi không nên loại bỏ các mô-đun ra khỏi tầm tay; có những lý do tốt để sử dụng chúng trong trường hợp phù hợp.
Tom Juergens

12

Nó được chấp nhận để sử dụng Module. Modulekhông được sử dụng để thay thế cho Class. Modulephục vụ mục đích riêng của nó. Mục đích của Moduleviệc sử dụng như một container cho

  • phương pháp mở rộng,
  • các biến không đặc trưng cho bất kỳ Class, hoặc
  • các biến không phù hợp đúng trong bất kỳ Class.

Modulekhông giống như Classvì bạn không thể

  • kế thừa từ một Module,
  • thực hiện một Interfacevới một Module,
  • cũng không tạo một thể hiện của a Module.

Bất cứ điều gì trong một Modulecó thể được truy cập trực tiếp trong Modulehội đồng mà không đề cập đến Moduletên của nó. Theo mặc định, mức truy cập cho một ModuleFriend.


11

Các lớp học

  • các lớp có thể được khởi tạo như các đối tượng
  • Dữ liệu đối tượng tồn tại riêng cho từng đối tượng khởi tạo.
  • các lớp có thể thực hiện các giao diện .
  • Các thành viên được định nghĩa trong một lớp được đặt trong một thể hiện cụ thể của lớp và chỉ tồn tại cho đời của đối tượng .
  • Để truy cập các thành viên lớp từ bên ngoài một lớp, bạn phải sử dụng các tên đủ điều kiện theo định dạng của Object.Member .

Mô-đun

  • Mô-đun không thể được khởi tạo dưới dạng đối tượng , vì chỉ có một bản sao dữ liệu của mô-đun chuẩn, khi một phần trong chương trình của bạn thay đổi biến công khai trong mô-đun chuẩn, nó sẽ hiển thị cho toàn bộ chương trình.
  • Các thành viên được khai báo trong một mô-đun là thể truy cập công khai theo mặc định.
  • Nó có thể được truy cập bởi bất kỳ mã nào có thể truy cập mô-đun.
  • Điều này có nghĩa là các biến trong một mô-đun chuẩn là các biến toàn cầu hiệu quả vì chúng có thể nhìn thấy từ bất kỳ đâu trong dự án của bạn và chúng tồn tại trong vòng đời của chương trình.

6

Khi một trong các lớp VB.NET của tôi có tất cả các thành viên được chia sẻ, tôi sẽ chuyển đổi nó thành Mô-đun với không gian tên phù hợp (hoặc phù hợp khác) hoặc tôi làm cho lớp không thể kế thừa và không thể xây dựng:

Public NotInheritable Class MyClass1

   Private Sub New()
      'Contains only shared members.
      'Private constructor means the class cannot be instantiated.
   End Sub

End Class

3
Và đây là cú pháp cho một module namespaced: Imports <whatever>nếu bạn có bất kỳ nhập khẩu, Namespace MyCoolModule, Public Module MyCoolModule, <thành viên mà không cần Shared >, End Module, End Namespace.
Rory O'Kane

0

Các mô-đun là tốt để lưu trữ enums và một số biến toàn cục, hằng và hàm chia sẻ. nó rất tốt và tôi thường sử dụng nó Các biến được khai báo có thể nhìn thấy toàn bộ dự án.


0

Bạn phải sử dụng Mô-đun (chứ không phải Lớp) nếu bạn đang tạo phương thức Tiện ích mở rộng. Trong VB.NET tôi không biết đến một lựa chọn khác.

Tự mình chống lại các Mô-đun, tôi chỉ mất vài giờ vô ích để cố gắng tìm cách thêm một số mã soạn sẵn để giải quyết các hội đồng nhúng trong một, chỉ để tìm ra rằng Sub New()(Mô-đun) và Shared Sub New()(Lớp) là tương đương. (Tôi thậm chí không biết có một callableSub New() trong một Module!)

Vì vậy, tôi chỉ cần ném EmbeddedAssembly.LoadAddHandler AppDomain.CurrentDomain.AssemblyResolvedòng trong đó và Bob đã trở thành chú của tôi.

Phụ lục : Tôi chưa kiểm tra 100% nhưng tôi có một loại mực Sub New()chạy theo thứ tự khác trong Mô-đun so với Lớp, chỉ cần thực tế là tôi phải chuyển một số khai báo sang bên trong từ bên ngoài để tránh lỗi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.