Experiment:
I have found it is possible to define both a "Module" (Namespace?) and a "Class" (Namespace?) within a single .Vb element (Module??).
You can try this at home:
- Create a new Console Application Project.
*A new .Vb element named "Module1.Vb" is automatically added to the project. - Add a new
Class
.Vb element by right-clicking on the project in Solution Explorer>Add>Class… - Give the new class the name
Test
. - View the code for "Test.Vb" and paste in the following:
Imports System.Runtime.CompilerServices
Module ExtensionsTest
<Extension()>
Public Sub ToConsole(ByVal Ex As Exception)
Dim ForeColor As ConsoleColor
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine()
Console.WriteLine("An unhandled exception has occurred!")
Console.WriteLine(Ex.ToString)
Console.ForegroundColor = ForeColor
End Sub
End Module
Class Test
Public Sub Test()
Try
Dim test As New Object
test.SomeMethodDoesntExist()
Catch ex As Exception
ex.ToConsole()
End Try
End Sub
End Class
View the Code for Module 1 and paste in the following:
Module Module1
Sub Main()
Try
Dim tester As New Test
tester.Test()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
End Module
Now go ahead and step through or run the application. You'll see it all works. So, let's move on to the…
Meat of the question
Is this acceptable practice?
It may be technically possible – but is it a bad solution for reasons I don't know? (I'm a Mort and really don't want pick up bad coding practices unwittingly)
I originally had this as a Private
method within the class definition like this:
Imports System.Runtime.CompilerServices
Class Test
Public Sub Test()
Try
Dim test As New Object
test.SomeMethodDoesntExist()
Catch ex As Exception
ToConsole(ex)
End Try
End Sub
Private Sub ToConsole(ByVal Ex As Exception)
Dim ForeColor As ConsoleColor
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine()
Console.WriteLine("An unhandled exception has occurred!")
Console.WriteLine(Ex.ToString)
Console.ForegroundColor = ForeColor
End Sub
End Class
I decided it would be cleaner to define the ToConsole
sub as an extension method for Exception
objects, but that's where I ran into trouble. When I created the Extension
attribute within the Class
namespace, I got a compiler error:
Extension methods can be defined only in modules.
So, I tried the above experiment and I declared a Module
within the same .VB element where my Class
is defined.
As the experiment above shows, this all compiles fine and works as expected, but I'd like to know if this is a good idea or not, and why?
Thanks for taking any time to read this and even more thanks for any time taken to comment or answer!
Best Answer
In general, the idea of one
Class
orModule
per file is something I first noticed in Java (I believe it is/was a requirement there). C# has continued this as a suggestion, and VB.NET probably now has the same suggestion somewhere.However, as the VB.NET designers decided you can only have extension methods in
Modules
, you've provided an example where it makes sense for another unit of code to be so closely related to anotherClass
as to include it in the same file.Of course, with the concept of
Partial
classes and modules you have the opposite idea of splitting single units across multiple files available too.And BTW this concept normally means your
Module
would be namedTestExtensions
:-)To your "Namespace?" notes in your question: VB.NET provides a Project-based namespace for your
Modules
andClasses
, so your classes are now namedProjectNamespace.UnitName
. If you provided athe enclosed units would be named
ProjectNamespace.SomeNamespace.UnitName
.You can have multiple
Namespaces
in a file too, and you can override theProjectNamespace
withGlobal.
:Rereading your question and noting the "(Module?)" note as well, I'm guessing you're actually asking what is the "formal" VB.NET term for code units that include
Class
andModule
and the similar term for a file of code. Because the .NET Module is so often equivalent to an Assembly, most people would know what you meant if you referred to "Namespace-level" code units as "modules", and source files are just "files". (There may be other places that give alternatve names, but I've based this on Microsoft's Introduction.)