Классы против модулей в VB.NET

157

Считается ли приемлемой практикой использование модулей вместо классов с общими функциями-членами в VB.NET?

Я стараюсь избегать модулей, потому что они чувствуют, что остались от Visual Basic 6.0 и, похоже, больше не подходят. С другой стороны, кажется, нет большой разницы между использованием модуля и класса только с общими элементами. Я не так уж часто нуждаюсь в них, но иногда бывают ситуации, когда они представляют простое решение.

Мне любопытно узнать, есть ли у вас мнение или предпочтения, так или иначе.

Том Юргенс
источник
10
Одним из интересных моментов для модулей является то, что по умолчанию методы и функции, объявленные внутри, имеют уровень защиты модуля, что означает, что вы можете непреднамеренно сделать методы доступными, если вы забудете явно добавить Privateклассификатор. В классе уровень защиты по умолчанию является закрытым, что может привести к путанице, если вы не знаете об этом.
yu_ominae

Ответы:

207

Modules являются аналогами VB для staticклассов C # . Если ваш класс предназначен исключительно для вспомогательных функций и методов расширения и вы не хотите разрешать наследование и создание экземпляров , вы используете a Module.

Кстати, использование Moduleне очень субъективно и не рекомендуется . На самом деле вы должны использовать, Moduleкогда это уместно. .NET Framework делает это много раз ( System.Linq.Enumerableнапример). Чтобы объявить метод расширения, необходимо использовать Modules.

Мехрдад Афшари
источник
7
Совершенно верно, хотя я могу использовать закрытый конструктор для предотвращения создания экземпляров и модификатор NotInheritable. Немного страшнее старого модуля, но имеет тот же эффект. Спасибо за указатель на использование модулей в платформе; Я посмотрю на это.
Том Юргенс
8
Под капотом они просто скомпилированы в классы с атрибутом [StandardModule]. Кроме того, использование модуля вынуждает вас не иметь там ничего общего, что хорошо.
Мердад Афшари
18
Модули - это не то же самое, что статические классы в C #. Методы в модуле являются по сути глобальными, если они находятся в импортированном пространстве имен.
JaredPar
2
@JaredPar: Моя формулировка, вероятно, плохая. Я должен был сказать VB аналоги статических классов C #. Из этого утверждения я хотел сказать, что использование модуля имеет смысл, когда вы пишете статический класс на C #.
Мердад Афшари
3
@Chiwda См. Msdn.microsoft.com/en-us/library/bb384936.aspx : «Методы расширения могут быть объявлены только внутри модулей».
Мердад Афшари
34

Я думаю, что стоит избегать модулей, если вы не вставляете их в отдельные пространства имен. Потому что в Intellisense методы в модулях будут видны из любого места в этом пространстве имен.

Таким образом, вместо того, чтобы ModuleName.MyMethod()вы в конечном итоге с MyMethod()всплывающими окнами в любом месте, и этот вид делает недействительным инкапсуляцию. (по крайней мере, на уровне программирования).

Вот почему я всегда пытаюсь создать Class с разделяемыми методами, кажется намного лучше.

др. злой
источник
7
Согласен, сейчас я работаю над старой программой (вероятно, с VB6 до VB.NET 1) с классами и модулями. Существуют сотни глобальных переменных, подпрограмм и функций примерно в десяти различных модулях, и это чертовски важно выяснить, что произошло, где и как оно было модифицировано.
yu_ominae
Хорошо, это очень старый, но относится к моему вопросу. Я не VB парень, но я должен работать с этим. Я пытаюсь разбить большой класс (> 46 000 строк), потому что IntelliSense / ReSharper просто умирают. Я обнаружил, что использование модулей и простое извлечение больших блоков функций в их собственный модуль, похоже, работает, но мне интересно, должен ли я дать каждому модулю свое собственное пространство имен. Это будет необходимо? то есть ускорит ли он IntelliSense только с модулями, или пространства имен помогут больше?
Codah
27

Модули ни в коем случае не являются устаревшими и интенсивно используются на языке VB. Это единственный способ, например, реализовать метод расширения в VB.Net.

Существует одно огромное различие между модулями и классами со статическими членами. Любой метод, определенный в модуле, доступен глобально, если модуль доступен в текущем пространстве имен. В сущности, модуль позволяет вам определять глобальные методы. Это то, чего не может сделать класс, имеющий только общих членов.

Вот быстрый пример, который я часто использую при написании кода VB, который взаимодействует с необработанными интерфейсами COM.

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
JaredPar
источник
4
Методы расширения ... еще одна замечательная функция, которую я всегда хочу использовать, но никогда не получаю - ну, это дает мне еще одну хорошую возможность. Я действительно немного разбираюсь в глобальной области видимости, и общедоступные методы, безусловно, могут быть удобными, но я чувствую некоторую тошноту из-за их чрезмерного использования. Во всяком случае, все ответы до сих пор говорят мне, что я не должен отклонять модули из-под контроля; Есть веские причины использовать их в правильных обстоятельствах.
Том Юргенс
12

Это приемлемо для использования Module. Moduleне используется в качестве замены Class. Moduleслужит своей цели. Целью Moduleявляется использование в качестве контейнера для

  • методы расширения,
  • переменные, которые не являются специфичными для любого Class, или
  • переменные, которые не вписываются должным образом ни в одну Class.

Moduleне как, Classтак как вы не можете

  • наследовать от Module,
  • реализовать Interfaceс Module,
  • и не создавать экземпляр Module.

К чему-либо внутри Moduleможно получить прямой доступ к Moduleсборке, не обращаясь к Moduleее имени. По умолчанию уровень доступа для a Moduleесть Friend.

Чандра Малла
источник
11

Классы

  • классы могут быть созданы как объекты
  • Данные объекта существуют отдельно для каждого экземпляра объекта.
  • классы могут реализовывать интерфейсы .
  • Члены, определенные в классе, находятся в определенном экземпляре класса и существуют только в течение всего времени существования объекта .
  • Чтобы получить доступ к членам класса извне класса, вы должны использовать полностью определенные имена в формате Object.Member .

Модули

  • Модули не могут быть созданы как объекты , поскольку существует только одна копия данных стандартного модуля, когда одна часть вашей программы изменяет открытую переменную в стандартном модуле, она будет видна всей программе.
  • Члены, объявленные в модуле, по умолчанию общедоступны .
  • Доступ к нему может получить любой код, который может получить доступ к модулю.
  • Это означает, что переменные в стандартном модуле по сути являются глобальными переменными, потому что они видны из любой точки вашего проекта и существуют в течение всей жизни программы.
Suji
источник
6

Когда один из моих классов VB.NET имеет всех общих членов, я либо преобразую его в модуль с соответствующим (или иным образом соответствующим) пространством имен, либо делаю класс не наследуемым и не конструируемым:

Public NotInheritable Class MyClass1

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

End Class
JRS
источник
3
И вот синтаксис для модуля пространства имен: Imports <whatever>если у вас есть какой - либо импорт, Namespace MyCoolModule, Public Module MyCoolModule, <члены без Shared > End Module, End Namespace.
Рори О'Кейн
0

Модули отлично подходят для хранения перечислений и некоторых глобальных переменных, констант и общих функций. это очень хорошая вещь, и я часто использую это. Объявленные переменные видны по всему проекту.

GGSoft
источник
0

Вы должны использовать модуль (а не класс), если вы создаете методы расширения. В VB.NET я не знаю другого варианта.

Будучи устойчивым к модулям, я потратил пару часов, пытаясь понять, как добавить некоторый шаблонный код для разрешения встроенных сборок в одной, только чтобы выяснить, что Sub New()(модуль) и Shared Sub New()(класс) эквивалентны. (Я даже не знал, что в модуле был вызываемый Sub New()модуль!)

Так что я просто бросил EmbeddedAssembly.Loadи AddHandler AppDomain.CurrentDomain.AssemblyResolveлинию там и Боб стал моим дядей.

Приложение : Я еще не проверил его на 100%, но у меня есть подозрение, что Sub New()в модуле он работает в ином порядке, чем в классе, просто исходя из того, что мне пришлось переместить некоторые объявления во внутренние методы извне, чтобы избежать ошибки.

SteveCinq
источник