I need help converting some of this code. Mainly:
private static void SetProvider(ServiceCollection collection)
=> _service = collection.BuildServiceProvider();
and the line below it. This is being used for a discord bot using Discord.Net with the music library Victoria. Can someone also tell me what this actually is? Just a side question. this uses static classes and there's not anything called static on VB.Net so what would be the best call here? I've seen some other posts from here debating whether to use NonInheritable Class or a Module. What are the differences and when it is better to use either one?
It depends on what you want exactly. VB.NET does not provide static classes. Instead, it offers modules, but those are not completely equal to static classes.
The module version would be:
Public Module ServiceManager
Private _service As IServiceProvider
Public Sub SetProvider(collection As ServiceCollection)
_service = collection.BuildServiceProvider()
End Sub
Public Function GetService(Of T As New)() As T
Return _service.GetRequiredService(Of T)()
End Function
End Module
The class version would be:
Public NotInheritable Class ServiceManager
Private Sub New()
End Sub
Private Shared _service As IServiceProvider
Public Shared Sub SetProvider(collection As ServiceCollection)
_service = collection.BuildServiceProvider()
End Sub
Public Shared Function GetService(Of T As New)() As T
Return _service.GetRequiredService(Of T)()
End Function
End Class
When using the class implementation, you have to be careful to mark all members as Shared. Additionally, you can consider the following:
Declare the class as NotInheritable, since neither VB.NET modules nor C# static classes can be inherited from. (The corresponding C# keyword is sealed, by the way, but it will never be used in this context, since C# does support static classes.)
Create one private (default) constructor for the class. That will make sure that you cannot instantiate the class. VB.NET modules nor C# static classes cannot be instantiated either.
Using VB.NET modules is somewhat more straightforward, but keep in mind that VB.NET modules have a little quirk. When accessing a member of a module, you are typically not required to prefix it with the module name. Suppose you have some kind of service class called MyService and you have implemented your ServiceManager as a module. Then you do not need to call it like:
Dim svc As MyService = ServiceManager.GetService(Of MyService)()
Instead, you could just call it like:
Dim svc As MyService = GetService(Of MyService)()`.
When using the former method, Visual Studio actually suggests to simplify the name and change it to the latter method. But when you afterwards add another imported namespace that also happens to contain a module that has a GetService(Of T)() method, you will get an error indicating that GetService is ambiguous, in which case you would be forced to prefix it with the module name (like in the former method).
I personally find this checking behavior in Visual Studio regarding VB.NET module member usage to be rather annoying and confusing. I prefer prefixing calls with the module name (for the sake of writing self-documenting code and avoiding ambiguity as mentioned), but I do not want to disable the "simplify name" hint/suggestion in Visual Studio. So I personally prefer a class implementation instead of a module implementation when implementing something in VB.NET that mimics a C# static class.
Or even better: I would avoid a static class design and switch to a "regular" class design when possible. Using class instances has several advantages, like using composition (which is also an important technique used in many popular behavioral design patterns), simplified mocking/unittesting, and less side effects in general.
The equivalent VB.NET is:
Private Shared Sub SetProvider(collection As ServiceCollection)
_service = collection.BuildServiceProvider()
End Sub
C# expression bodies are just a single expression body method, MS Docs e.g. the following are equivalent:
void Greet()
{
Console.WriteLine("Hello World");
}
// Same as above
void Greet() => Console.WriteLine("Hello World");
Related
Is using the Named Constructor Idiom possible in VB.NET? I've found many examples in C#/C++ but can't quite wrap my head around how to use it in vb.net. Seems like a better method of keeping my code readable when involving a lot of constructors with similar argument types.
I've never heard this term before, but after a quick search it sounds vaguely like the Static Factory Pattern. The idea is you make the constructor private and use a shared (static in c#) public function to create the new object.
Public Class Foo
Private Sub New()
End Sub
Public Shared Function CreateNew(param as Object) as Foo
Dim obj as New Foo()
obj.Prop = param
return obj
End Function
End Class
You sure can make Named Constructors in VB. The pattern uses a static (Shared in VB) factory method on the class itself, so that the method can be named. (Other Factory patterns involve using a separate Factory class to provide the static method.)
System.Drawing.Color is a simple example. The pattern is implemented underneath as a static (Shared) property. Since no arguments are necessary, the Get method of a Property works just fine:
Public Shared ReadOnly Property Chartreuse As Color
Usage:
Dim favoriteColor as Color = Color.Chartreuse
Or you can make static factory methods to do the same thing.
Public Class TheClass
Public Sub New()
End Sub
Public Sub New(input As String)
'do something with input
End Sub
Public Shared Function MyNamedConstructor() As TheClass
Return New TheClass
End Function
Public Shared Function AnotherNamedConstructor() As TheClass
Return New TheClass("Another Name")
End Function
End Class
As for whether this pattern is "better" than overloading constructors, that's really an opinion. Personally, I would just overload the constructors. As you can see in the example above, the constructors need to be there anyway.
I suggest using the Named Constructor pattern when you have only a few possible ways to construct your class/struct, but consumers of your class/struct will be using those few constructors often, and with different input values to those constructors (as in the System.Drawing.Color example).
The Name in 'Named Constructor' doesn't represent a name for the constructor itself, but for the object resulting from the constructor. If your named constructor can be used to create two objects that don't feel right to give the same name to, then don't give the constructor that name.
I can read a lot over the Internet that VB.Net Modules are the same thing as c#.Net Static Classes. I can also read that something close to a Static Class is a class which would look like this:
'NotInheritable so that no other class can be derived from it
Public NotInheritable Class MyAlmostStaticClass
'Private Creator so that it cannot be instantiated
Private Sub New()
End Sub
'Shared Members
Public Shared Function MyStaticFunction() as String
Return "Something"
End Function
End Class
I find this code heavy to draft, and to read. I would be much more confortable just using a Module like this:
Public Module MyEquivalentStaticClass
Public Function MyStaticFunction() as String
Return "Something"
End Function
End Module
However, with a Module you loose one level of Namespace hierarchy, and the following 3 statements are equal:
'Call through the Class Name is compulsory
Dim MyVar as String = Global.MyProject.MyAlmostStaticClass.MyStaticFunction()
'Call through the Module Name is OPTIONAL
Dim MyVar as String = Global.MyProject.MyEquivalentStaticClass.MyStaticFunction()
Dim MyVar as String = Global.MyProject.MyStaticFunction()
I find this very inconvenient and this either pollutes the Intelisense, or forces me to create additionnal levels of Namespace, which then means more Module declaration, i.e., more Intelisense pollution.
Is there a workaround or is this the price to pay if you want to avoid the heavy SharedMembers-NotInheritable-PrivateNew Class declaration?
Additionnal references include the very good post by Cody Gray: https://stackoverflow.com/a/39256196/10794555
No, there is no exact equivalent to a C# static class in VB.NET. It would be nice if VB had the ability to add the Shared modifier to a class declaration, like this:
Public Shared Class Test ' This won't work, so don't try it
' Compiler only allows shared members in here
End Class
But, unfortunately, it does not. If you do that, the compiler gives you the following error:
Classes cannot be declared 'Shared'
That leaves us with the two options you listed:
Either you make a non-instantiable class containing only Shared members (without the safety of that rule being enforced by the compiler), or
Use a Module, which makes everything Shared, even though you don't explicitly say so via the Shared modifier
As you said, many people don't like the loss of the class name being required, as a sort-of extra namespace layer, so they prefer the Class with only Shared members over the Module. But, that's a matter of preference.
It's worth noting that, while you don't have to specify the module name everywhere you call its members, you can always do so if you wish:
MyModule.MyMethod()
While a "SharedMembers-NotInheritable-PrivateNew Class", as you so eloquently called it, is the closest approximation to a static class, it's only functionally equivalent. If you use reflection, you'll see that the attributes of the type are not the same. For instance, in VB:
Module MyModule
Public Sub Main()
Dim t As Type = GetType(MyClass)
End Sub
End Module
Public NotInheritable Class MyClass
Private Sub New()
End Sub
Public Shared Sub MyMethod()
End Sub
End Class
If you take a look at t.Attributes, you'll see that it equals Public Or Sealed. So the MyClass type is both sealed (NotInheritable) and public. However, if you do this in C#:
class Program
{
static void Main(string[] args)
{
Type t = typeof(Test);
}
}
public static class MyClass
{
public static void MyMethod()
{ }
}
And you inspect the t.Attributes again, this time, the value is Public | Abstract | Sealed | BeforeFieldInit. That's not the same. Since you can't declare a class in VB as both NotInheritable and MustInherit at the same time, you have no chance of exactly duplicating that thing. So, while they more-or-less are equivalent, the attributes of the types are different. Now, just for fun, let's try this:
Module MyModule
Public Sub Main()
Dim t As Type = GetType(MyModule)
End Sub
End Module
Now, the t.Attributes for the module are Sealed. That's it. Just Sealed. So that's not the same either. The only way to get a true static class in VB (meaning, the type has the same attributes when inspected via reflection) is to write it in a C# class library, and then reference the library in VB.
I would be much more confortable just using a Module
So use a Module.
Module SomeModuleNameHere
Public Function MyStaticFunction() As String
Return "Something"
End Function
End Module
You don't need Global.MyProject or the Module name at all, just call your function directly, from anywhere:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim x As String = MyStaticFunction()
Debug.Print(x)
End Sub
But if you want to, you can use the Module name, without the Global part:
Dim x As String = SomeModuleNameHere.MyStaticFunctions
The only time you must use the Module name, however, is if you have two functions with the exact same name in different modules. Then you'd have to differentiate them by using their fully qualified names.
From all the discussions held so far, and thanks to the input by Steven Doggart and comments by TnTinMn, I have come to conclude with the following broad feedbacks and guidelines.
Nota: This post refers to 'Static' Classes, whilst the Static keyword is used for C#.Net, not VB.Net. The VB equivalent is Shared, but Shared Classes are not permited with VB (only the Members). The guidelines described below are tentatives to achieve in VB something close to a C# Static Class.
Since such VB Classes cannot be Shared, they are described as 'Static'.
Nota bis: In all the examples, I purposely added a layer of Namespace (consistently called "MySpace") so that there is no confusing as to in which Namespace layer the examples sit: they are all in the MySpace layer. The MySpace layer is not compulsory and can be stripped out depending on your needs.
In general
Use a Module but do not rely on the Module name as a Namespace layer. Rather, fully integrate the path in a Namespace declaration, such as:
Namespace MySpace.MyStaticClass
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Then the Static 'Members' should be accessed via Global.MyProject.MySpace.MyStaticClass.MyStaticFunction()
Nota: Part of the Namespace path can be stripped depending on where
you are located. Usually, MySpace.MyStaticClass.MyStaticFunction()
will be sufficient.
Nota bis: Using _Module as the Module name will
reduce the appereance of the Module in the Intelisense dropdown, and
yet make it crystal clear this is a Module.
When wishing to encaspulate Static Classes
Under such context the general above-mentionned style would produce:
Namespace MySpace.MyStaticClass
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Namespace MySpace.MyStaticClass.MyStaticSubClass1
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
Namespace MySpace.MyStaticClass.MyStaticSubClass2
Module _Module
Function MyStaticFunction()
Return "Something"
End Function
End Module
End Namespace
This can quickly be heavy in the sense that it requires a separate Namespace declaration for each 'encapsulated' 'Static Class'. Disadvantages include:
Heavy review because understanding the Namespace architecture/arborescence will be less intuitive: in the above example that would mean checking all the declaration which include 'MyStaticClass'.
Heavy drafting because of the additionnal Namespace declarations.
Heavy maintenance because changing a parent Namespace will require a change in several Namespace declarations: in the above example that would mean changing 'MyStaticClass' 3 times. (Right-Click/Rename is your best friend here)
An alternative is to use encapsulated Classes with Shared members:
Namespace MySpace
Public Class MyStaticClass
Public Function MyStaticFunction()
Return "Something"
End Function
Public Class MyStaticSubClass1
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public Class MyStaticSubClass2
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Class
End Namespace
Nota: As Steven Doggart pointed out in a separate post, people usually import Namespaces, but do not import Classes, so encapsulating Classes will usually "force" the reliance on the full path across encapsulated Classes : MyStaticClass.MyStaticSubClass1.
You cannot encapsulate a Module within another Module, but you could always use a mixture of a Module in which you encapsulate one or several Classes and Sub-Classes. The example below achieves something similar to the above example:
Namespace MyStaticClass
Public Module _Module
Public Function MyStaticFunction()
Return "Something"
End Function
Public Class MyStaticSubClass1
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public Class MyStaticSubClass2
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Module
End Namespace
When publishing a Class Library (DLL)
If your final product is a DLL you intend to share with a broader audience, it is recommended to put safety nets around your 'Static' Classes. Although this will not affect how the compiler will see your code, it will prevent someone else from making mistakes, or at least quickly trigger errors and assist debugging swiftly:
Make the Class NotInheritable, so that no one tries to derive a Class from a Static Class: it is typically useless to derive such Classes.
Make the New Creator statement Private, so that no one tries to instantiate the Class: the Static Class should not include any non-Static (Shared) members; if so, that is a typo and trying to instantiate the non-Shared Member will likely bring problems.
The example below achieves something similar to the above examples:
Namespace MySpace
Public NotInheritable Class MyStaticClass
Private Sub New()
End Sub
Public Function MyStaticFunction()
Return "Something"
End Function
Public NotInheritable Class MyStaticSubClass1
Private Sub New()
End Sub
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
Public NotInheritable Class MyStaticSubClass2
Private Sub New()
End Sub
Public Shared Function MyStaticFunction()
Return "Something"
End Function
End Class
End Class
End Namespace
When dealing with an Extension
A <System.Runtime.CompilerServices.Extension()> can only be declared within a Module block. However the Module Name has no impact on the Extension so this topic is not really relevant here.
See link provided by Peter Macej: https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/procedures/extension-methods
Interface behaves differently in Vb.Net. Below is a sample code snippet where IStudent interface has a method SayHello which is implemented by a class Student. The Access modifier for SayHello should be Public by default. By changing Access modifier to Private is not breaking the existing code and still i can access this private method using below code
Dim stdnt As IStudent = New Student
stdnt.SayHello()
Access modifier determines the scope of the members in a class, more over private members are accessible only from the class which exists. But here the theory of Access Modifier, Encapsulation are broken.
Why .net has designed in this way?
Is the concept of Access modifier and encapsulation are really broken?
How .net framework internally handle this situation?
Thanks in advance
Module Module1
Sub Main()
Dim stdnt As IStudent = New Student
stdnt.Name = "vimal"
stdnt.SayHello()
End Sub
End Module
Public Interface IStudent
Property Name As String
Sub SayHello()
End Interface
Public Class Student
Implements IStudent
Private Property Name As String Implements IStudent.Name
Private Sub SayHello() Implements IStudent.SayHello
Console.WriteLine("Say Hello!")
End Sub
End Class
The original poster submitted this question to me via TheBugGuys#Coverity.com; my answer is here:
https://communities.coverity.com/blogs/development-testing-blog/2013/10/09/oct-9-posting-interface-behaves-differently-in-visual-basic
To briefly summarize:
Why was .NET designed in this way?
That question is impossibly vague.
Is encapsulation broken by explicit implementation in C# and VB?
No. The privacy of the method restricts the accessibility domain of the methods name, not who can call the method. If the author of the class chooses to make a private method callable by some mechanism other than looking it up by name, that is their choice. A third party cannot make the choice for them except via techniques such as private reflection, which do break encapsulation.
How is this feature implemented in .NET?
There is a special metadata table for explicit interface implementations. The CLR consults it first when attempting to figure out which class (or struct) method is associated with which interface method.
From MSDN:
You can use a private member to implement an interface member. When a private member implements a member of an interface, that member becomes available by way of the interface even though it is not available directly on object variables for the class.
In C#, this behaviour is achieved by implementing the interface explicitly, like this:
public interface IStudent {
string Name { get; set; }
void SayHello();
}
public class Student : IStudent {
string IStudent.Name { get; set; }
void IStudent.SayHello() {
Console.WriteLine("Say Hello!");
}
}
So, if you were to omit the IStudent. in front of the method names, it would break. I see that in the VB syntax the interface name is included. I don't know whether this has any implications altough. But interface members aren't private, since the interface isn't. They're kinda public...
There is no fundamental difference between C# and VB.NET, they just chose different ways to solve ambiguity. Best demonstrated with a C# snippet:
interface ICowboy {
void Draw();
}
interface IPainter {
void Draw();
}
class CowboyPainter : ICowboy, IPainter {
void ICowboy.Draw() { useGun(); }
void IPainter.Draw() { useBrush(); }
// etc...
}
VB.NET just chose consistent interface implementation syntax so the programmer doesn't have to weigh the differences between implicit and explicit implementation syntax. Simply always explicit in VB.NET.
Only the accessibility of the interface method matters. Always public.
When your variable stdnt is declared as IStudent, the interface methods and properties are then made Public, so the derived class' (Student) implementation is executed. If, on the other hand, if stdnt was declared as Student, the private members (Name and SayHello) would not be implemented, and an error would be thrown.
I'm guessing that the Interface members stubs (Name & SayHello) are by default Public, and the access modifier definitions of the derived class' implementation are ignored.
IMHO.
The exact equivalent in C# is the following - the method available to objects of the interface type and the private method available otherwise:
void IStudent.SayHello()
{
this.SayHello();
}
private void SayHello()
{
Console.WriteLine("Say Hello!");
}
Interface behaves differently in Vb.Net. Below is a sample code snippet where IStudent interface has a method SayHello which is implemented by a class Student. The Access modifier for SayHello should be Public by default. By changing Access modifier to Private is not breaking the existing code and still i can access this private method using below code
Dim stdnt As IStudent = New Student
stdnt.SayHello()
Access modifier determines the scope of the members in a class, more over private members are accessible only from the class which exists. But here the theory of Access Modifier, Encapsulation are broken.
Why .net has designed in this way?
Is the concept of Access modifier and encapsulation are really broken?
How .net framework internally handle this situation?
Thanks in advance
Module Module1
Sub Main()
Dim stdnt As IStudent = New Student
stdnt.Name = "vimal"
stdnt.SayHello()
End Sub
End Module
Public Interface IStudent
Property Name As String
Sub SayHello()
End Interface
Public Class Student
Implements IStudent
Private Property Name As String Implements IStudent.Name
Private Sub SayHello() Implements IStudent.SayHello
Console.WriteLine("Say Hello!")
End Sub
End Class
The original poster submitted this question to me via TheBugGuys#Coverity.com; my answer is here:
https://communities.coverity.com/blogs/development-testing-blog/2013/10/09/oct-9-posting-interface-behaves-differently-in-visual-basic
To briefly summarize:
Why was .NET designed in this way?
That question is impossibly vague.
Is encapsulation broken by explicit implementation in C# and VB?
No. The privacy of the method restricts the accessibility domain of the methods name, not who can call the method. If the author of the class chooses to make a private method callable by some mechanism other than looking it up by name, that is their choice. A third party cannot make the choice for them except via techniques such as private reflection, which do break encapsulation.
How is this feature implemented in .NET?
There is a special metadata table for explicit interface implementations. The CLR consults it first when attempting to figure out which class (or struct) method is associated with which interface method.
From MSDN:
You can use a private member to implement an interface member. When a private member implements a member of an interface, that member becomes available by way of the interface even though it is not available directly on object variables for the class.
In C#, this behaviour is achieved by implementing the interface explicitly, like this:
public interface IStudent {
string Name { get; set; }
void SayHello();
}
public class Student : IStudent {
string IStudent.Name { get; set; }
void IStudent.SayHello() {
Console.WriteLine("Say Hello!");
}
}
So, if you were to omit the IStudent. in front of the method names, it would break. I see that in the VB syntax the interface name is included. I don't know whether this has any implications altough. But interface members aren't private, since the interface isn't. They're kinda public...
There is no fundamental difference between C# and VB.NET, they just chose different ways to solve ambiguity. Best demonstrated with a C# snippet:
interface ICowboy {
void Draw();
}
interface IPainter {
void Draw();
}
class CowboyPainter : ICowboy, IPainter {
void ICowboy.Draw() { useGun(); }
void IPainter.Draw() { useBrush(); }
// etc...
}
VB.NET just chose consistent interface implementation syntax so the programmer doesn't have to weigh the differences between implicit and explicit implementation syntax. Simply always explicit in VB.NET.
Only the accessibility of the interface method matters. Always public.
When your variable stdnt is declared as IStudent, the interface methods and properties are then made Public, so the derived class' (Student) implementation is executed. If, on the other hand, if stdnt was declared as Student, the private members (Name and SayHello) would not be implemented, and an error would be thrown.
I'm guessing that the Interface members stubs (Name & SayHello) are by default Public, and the access modifier definitions of the derived class' implementation are ignored.
IMHO.
The exact equivalent in C# is the following - the method available to objects of the interface type and the private method available otherwise:
void IStudent.SayHello()
{
this.SayHello();
}
private void SayHello()
{
Console.WriteLine("Say Hello!");
}
I have a class that looks like the following:
Public Class Utilities
Public Shared Function blah(userCode As String) As String
'doing some stuff
End Function
End Class
I'm running FxCop 10 on it and it says:
"Because type 'Utilities' contains only 'static' (
'Shared' in Visual Basic) members, add a default private
constructor to prevent the compiler from adding a default
public constructor."
Ok, you're right Mr. FxCop, I'll add a private constructor:
Private Utilities()
Now I'm having:
"It appears that field 'Utilities.Utilities' is
never used or is only ever assigned to. Use this field
or remove it."
Any ideas of what should I do to get rid of both warnings?
In C# this problem would be handled by marking the class as static, e.g.
public static class Utilities
{
...
}
A static class can only contain static (in VB shared) members.
I believe the equivalent in VB.NET is to use a module.
See Marking A Class Static in VB.NET.