Parameterless constructor in Structure - vb.net

Following on from this question on using different Visual Basic versions in Visual Studio 2015, I'm running through the new lanugage features in Visual Basic 14, as documented here and here.
One of those is the ability to have parameterless constructors in structures, like this:
Structure MyStruct1
Public f As Integer
Sub New()
f = 15
End Sub
End Structure
When I try this in code in Visual Studio 2015, I'm still getting an red error squiggle under the New():
BC30629 Structures cannot declare a non-shared 'Sub New' with no parameters.
I haven't seen anywhere that states that this got pulled before release.
Am I mis-understanding what this new feature does?

As you can see in the quoted text below, Roslyn removed support for structures with parameterless constructors, and therefore it's not listed as a new feature in VB 14.
It has been a long standing requirement that C# and VB struct
constructors would always have parameters. We have tried to relax this
requirements in C#6.0 to make structs more consistent with classes.
While overall parameterless constructors in structs are valid from IL
perspective, without a convenient way to declare them they were
virtually nonexistent. As we performed more and more testing, we kept
discovering cases where parameterless struct constructors caused
inconsistent behavior in libraries or even in some versions of CLR.
A good example is the issue reported in the CodePlex bug http://roslyn.codeplex.com/workitem/465. The issue is basically an
optimization introduced in Activator.CreateInstance around CLR 4.0 and
present ever since. The optimization assumes that parameterless
instantiation of generic T type does not cause sideeffects if T is
found to be a struct and therefore instances can be cached.
Parameterless struct constructors would violate such assumptions and
make optimization observable, thus necessitating servicing of existing
code several versions back.
After reconsidering the potential issues arising from breaking long
standing assumptions, we decided it was best for our users to restore
the requirement on struct constructors to always have formal
parameters.
Source: Restore requirement for struct constructors to always have formal parameters. #1029

You need to use Shared Keyword(acts as static) for a Parameter less Constructor in VB.Net.
Try the code below:
Structure MyStruct1
Public Shared f As Integer
Shared Sub New()
f = 15
End Sub
End Structure
Class My_Class
Public Shared Sub Main()
Dim str1 As New MyStruct1()
End Sub
End Class
Note: Shared keyword here acts as static. While using a Shared Constructor you need to access Shared variables, that is why I have declared the variable with Shared keyword.

Related

What is the use of Module in VB.Net programming?

I am creating a .dll for a CAD tool I use.
After creating a new project (class library) , I got a "public class-end class" block.
I wrote my main method inside that block. When I run the dll in my CAD tool, its giving me main entry point missing error.
So i come back and change the "public class-end class" ---> "Public Module-end Module".
Now its able to find the main method.
Why is this so? Ive read on these forums that we should not be using modules as much.
If I were to not use modules so much, how I am supposed to make it work without the module block?
VB.Net doesn't have static classes like C# has. Static classes allow you to create static methods such that
class foo
{
void bar() {}
}
Accessed in VB.Net like this
foo.bar()
If you want to create the same functionality with VB.Net you have two options, which are either using a Module
Module foo1
Sub bar()
End Sub
End Module
Class foo2
Shared Sub bar()
End Sub
End Class
However the difference is how Module and Class are scoped. Modules are globally scoped so you can call the module method outside of the originating namespace without qualifying it with the Module name, but to call the static method you need to qualify it with the class name, and even import the namespace in the case of a class with static method
bar()
foo2.bar()
But what Modules are certainly good for is Extension Methods, and the global scope actually helps here if you want to extend a class across your project
Module Extensions
<Extension>
Sub bar(value As String)
End Sub
End Module
Dim s = "my string"
s.bar()
In your case, it's expecting a C# style static class with method, and since VB.Net doesn't have static classes, a Module or class with static method both satisfy that.
Modules come from legacy versions of Visual Basic and sort of act as the "OG" of Visual Basic code files. When Visual Basic 6 and earlier was around, Visual Basic was sort of quasi object oriented and while classes existed, it made more sense to use modules in lieu of static classes. Then when Visual Basic .NET was introduced, Microsoft made a real effort to make the programming language a true object oriented programming language.
People likely tell you to use classes over modules because modules are holdovers from the days prior to Visual Basic being a pure object oriented language. Starting from 2005 on forward, anything you could do in a module could basically be done as a static (aka shared) only class with the exception of extension methods. So by using classes over modules, you're taking a more .NET oriented approach rather than a Visual Basic first approach.
With regards to your specific problem, the issue is that your CAD tool is looking for an entry method, but cannot find one. The simple solution is to add a shared method:
Public Class MyClass
Public Shared Sub Main()
' ...
End Sub
End Class

VB.NET code re-ordering to interface

Is there a simple way, without using external tools, to get the physical layout of my classes to match my interface?
If I have an interface, IFoo:
Interface IFoo
Function DoFoo() As Integer
Function DoBar() As Integer
End Function
I will end up with a class:
Class MyFoo
Public Function DoFoo() As Integer Implements IFoo.DoFoo
'...
End Function
Public Function DoBar() As Integer Implements IFoo.DoBar
'...
End Function
End Function
I then decide to add GetFoo() to my interface. I put it with DoFoo(), since it is a related thing and I want to group like terms. Visual Studio then tells me that the class no longer implements IFoo properly. The autogenerated code goes at the end of MyFoo.
What I would like to do is either get the item to be inserted in the correct place (under the previous item in the interface), or moved there post-event.
Not had anything very relevant come up using Google.
There is not such functionality in Visual Studio. For this, I am using CodeMaid extension, which can arrange VB.NET code alphabetically and by type and scope. It really makes your code beautiful. There is also very good commercial extension called CodeRush for Roslyn which have much more features and it does organizing document little better.

Declare global variables in Visual Studio 2010 and VB.NET

How do I declare a global variable in Visual Basic?
These variables need to be accessible from all the Visual Basic forms. I know how to declare a public variable for a specific form, but how do I do this for all the forms in my project?
There is no way to declare global variables as you're probably imagining them in VB.NET.
What you can do (as some of the other answers have suggested) is declare everything that you want to treat as a global variable as static variables instead within one particular class:
Public Class GlobalVariables
Public Shared UserName As String = "Tim Johnson"
Public Shared UserAge As Integer = 39
End Class
However, you'll need to fully-qualify all references to those variables anywhere you want to use them in your code. In this sense, they are not the type of global variables with which you may be familiar from other languages, because they are still associated with some particular class.
For example, if you want to display a message box in your form's code with the user's name, you'll have to do something like this:
Public Class Form1: Inherits Form
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
MessageBox.Show("Hello, " & GlobalVariables.UserName)
End Sub
End Class
You can't simply access the variable by typing UserName outside of the class in which it is defined—you must also specify the name of the class in which it is defined.
If the practice of fully-qualifying your variables horrifies or upsets you for whatever reason, you can always import the class that contains your global variable declarations (here, GlobalVariables) at the top of each code file (or even at the project level, in the project's Properties window). Then, you could simply reference the variables by their name.
Imports GlobalVariables
Note that this is exactly the same thing that the compiler is doing for you behind-the-scenes when you declare your global variables in a Module, rather than a Class. In VB.NET, which offers modules for backward-compatibility purposes with previous versions of VB, a Module is simply a sealed static class (or, in VB.NET terms, Shared NotInheritable Class). The IDE allows you to call members from modules without fully-qualifying or importing a reference to them. Even if you decide to go this route, it's worth understanding what is happening behind the scenes in an object-oriented language like VB.NET. I think that as a programmer, it's important to understand what's going on and what exactly your tools are doing for you, even if you decide to use them. And for what it's worth, I do not recommend this as a "best practice" because I feel that it tends towards obscurity and clean object-oriented code/design. It's much more likely that a C# programmer will understand your code if it's written as shown above than if you cram it into a module and let the compiler handle everything.
Note that like at least one other answer has alluded to, VB.NET is a fully object-oriented language. That means, among other things, that everything is an object. Even "global" variables have to be defined within an instance of a class because they are objects as well. Any time you feel the need to use global variables in an object-oriented language, that a sign you need to rethink your design. If you're just making the switch to object-oriented programming, it's more than worth your while to stop and learn some of the basic patterns before entrenching yourself any further into writing code.
Pretty much the same way that you always have, with "Modules" instead of classes and just use "Public" instead of the old "Global" keyword:
Public Module Module1
Public Foo As Integer
End Module
Okay. I finally found what actually works to answer the question that seems to be asked;
"When needing many modules and forms, how can I declare a variable to be public to all of them such that they each reference the same variable?"
Amazingly to me, I spent considerable time searching the web for that seemingly simple question, finding nothing but vagueness that left me still getting errors.
But thanks to Cody Gray's link to an example, I was able to discern a proper answer;
Situation;
You have multiple Modules and/or Forms and want to reference a particular variable from each or all.
"A" way that works;
On one module place the following code (wherein "DefineGlobals" is an arbitrarily chosen name);
Public Module DefineGlobals
Public Parts As Integer 'Assembled-particle count
Public FirstPrtAff As Long 'Addr into Link List
End Module
And then in each Module/Form in need of addressing that variable "Parts", place the following code (as an example of the "InitForm2" form);
Public Class InitForm2
Private Sub InitForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Parts = Parts + 3
End Sub
End Class
And perhaps another Form;
Public Class FormX
Sub CreateAff()
Parts = 1000
End Sub
End Class
That type of coding seems to have worked on my VB2008 Express and seems to be all needed at the moment (void of any unknown files being loaded in the background) even though I have found no end to the "Oh btw..." surprise details. And I'm certain a greater degree of standardization would be preferred, but the first task is simply to get something working at all, with or without standards.
Nothing beats exact and well worded, explicit examples.
Thanks again, Cody
Make it static (shared in VB).
Public Class Form1
Public Shared SomeValue As Integer = 5
End Class
Public variables are a code smell - try to redesign your application so these are not needed. Most of the reasoning here and here are as applicable to VB.NET.
The simplest way to have global variables in VB.NET is to create public static variables on a class (declare a variable as Public Shared).
A global variable could be accessible in all your forms in your project if you use the keyword public shared if it is in a class. It will also work if you use the keyword "public" if it is under a Module, but it is not the best practice for many reasons.
(... Yes, I somewhat repeating what "Cody Gray" and "RBarryYoung" said.)
One of the problems is when you have two threads that call the same global variable at the same time. You will have some surprises. You might have unexpected reactions if you don't know their limitations. Take a look at the post Global Variables in Visual Basic .NET and download the sample project!
small remark: I am using modules in webbased application (asp.net).
I need to remember that everything I store in the variables on the module are seen by everyone in the application, read website. Not only in my session.
If i try to add up a calculation in my session I need to make an array to filter the numbers for my session and for others.
Modules is a great way to work but need concentration on how to use it.
To help against mistakes: classes are send to the
CarbageCollector
when the page is finished. My modules stay alive (as long as the application is not ended or restarted) and I can reuse the data in it.
I use this to save data that sometimes is lost because of the sessionhandling by IIS.
IIS Form auth
and
IIS_session
are not in sync, and with my module I pull back data that went over de cliff.
All of above can be avoided by simply declaring a friend value for runtime on the starting form.
Public Class Form1
Friend sharevalue as string = "Boo"
Then access this variable from all forms simply using Form1.sharevalue
You could just add a new Variable under the properties of your project
Each time you want to get that variable you just have to use
My.Settings.(Name of variable)
That'll work for the entire Project in all forms
The various answers in this blog seem to be defined by SE's who promote strict adherence to the usual rules of object-oriented programming (use a Public Class with public shared (aka static), and fully-qualified class references, or SE's who promote using the backward-compatibility feature (Module) for which the compiler obviously needs to do the same thing to make it work.
As a SE with 30+ years of experience, I would propose the following guidelines:
If you are writing all new code (not attempting to convert a legacy app) that you avoid using these forms altogether except in the rare instance that you really DO need to have a static variable because they can cause terrible consequences (and really hard-to-find bugs). (Multithread and multiprocessing code requires semaphores around static variables...)
If you are modifying a small application that already has a few global variables, then formulate them so they are not obscured by Modules, that is, use the standard rules of object-oriented programming to re-create them as public static and access them by full qualification so others can figure out what is going on.
If you have a huge legacy application with dozens or hundreds of global variables, by all means, use Modules to define them. There is no reason to waste time when getting the application working, because you are probably already behind the 8-ball in time spent on Properties, etc.
The first guy with a public class makes a lot more sense. The original guy has multiple forms and if global variables are needed then the global class will be better. Think of someone coding behind him and needs to use a global variable in a class you have IntelliSense, it will also make coding a modification 6 months later a lot easier.
Also if I have a brain fart and use like in an example parts on a module level then want my global parts I can do something like
Dim Parts as Integer
parts = 3
GlobalVariables.parts += Parts '< Not recommended but it works
At least that's why I would go the class route.
You can pipe the variable in to a file in the output directory and then load that file in the variable.
Imports System.IO
This code writes the file.
Dim somevariable = "an example"
Dim fs As FileStream = File.Create("globalvars/myvar1.var")
Dim filedata As Byte() = New UTF8Encoding(True).GetBytes(somevariable)
fs.Write(filedata, 0, filedata.Length)
fs.Close()
This loads the file in another form.
Dim form2variable
Dim fileReader As String
fileReader = My.Computer.FileSystem.ReadAllText("globalvars/myvar1.var")
form2variable = filereader
Public Class Form1
Public Shared SomeValue As Integer = 5
End Class
The answer:
MessageBox.Show("this is the number"&GlobalVariables.SomeValue)

Why are public fields and properties interchangeably binary compatible?

In the day job, I work on a VB6 (I know, but don't mock the afflicted...) application that uses a number of libraries we have written (also in the ever illustrious VB6). One of these supporting libraries had a load of private members exposed via public properties, and I was asked to remove the properties, and promote the private member variables into public fields with the same name as the original properties.
Now, I'm no COM expert, but I was under the impression that each and every exposed item on a class gets it's own GUID. Since we would be going from a situation where each value went from 2 Guids (Property Get and Property Let) to one where they only used the one (the public field), I was expecting this to break binary compatibility - but it seems it hasn't done that.
Can anyone explain why?
No, it hasn't broken compatibility because it hasn't removed the property get and property let methods. It's just that the compiler is now writing them for you.
Isn't this one of the few areas where VB6 is arguably better than .Net?
In .Net public fields behave differently to public properties, and this makes some refactorings difficult and causes confusion.
In VB6 public fields behave exactly like public properties, which is why it's possible to switch without affecting binary compatibility. Behind the scenes, the compiler generates property get and set routines for public fields. In a sense VB6 has automatically implemented properties (now advertised as a "new feature" in VB10)...
I think it's a bit more subtle than that. You get a GUID for the COM interface (not each individual field/method). As I understand it the binary compatibility attempts to work out if the interface your currently compiling is backwards compatible with a reference version of your DLL (assuming you have one) and only changes the GUID if they are not compatible.
I'm therefore also surprised that it has decided removing all the get/set methods is compatible :/

Problem overriding methods in VB.NET (Error BC30284)

I have an overridable sub in my base class
Project1:
Public Class BaseClass
Protected Overridable Sub MySub(ByVal Parameter as MyType)
End Class
Project2:
Public Class DerivedClass
Inherits BaseClass
Protected Overrides Sub MySub(ByVal Parameter as MyType)
End Class
MyType is a type that comes from external COM library. When I'm trying to override it in a derived class, I'm getting
error BC30284: sub 'MySub' cannot be declared 'Overrides' because it does not override a function in a base class
I've added the required COM reference to both projects containing base and derived classes.
Any idea how to get rid of this error? I'm using VS2005 and .NET 2.0
Edit: Every other override is working fine, I'm only getting error if I'm using referenced COM types as parameters. If I change Parameter to Object, overriding works fine.
Have you considered or tried using TlbImp.exe to generate a static DLL from the COM type library, and reference that from both projects (instead of using a COM reference) to make sure they are referring to exactly the same thing? TlbImp is included with Visual Studio, but I can't find it on my system with only Visual Studio Express installed, so if you're using express, you might have to go hunting for it (the linked page may or may not have the version you want). I suspect that if each project has their own COM reference, Visual Studio may be creating a separate COM wrapper for each project and the generated COM wrappers may not entirely agree with each other when it comes to generated GUIDs and whatnot. So by creating a and forcing the use of a single wrapper you may be able to eliminate that as a possible problem.
Rather than using TlbImp, another option is to have a separate project where you encapsulate the MyType in a .NET class and include that project in both your samples.
So you would end up with an intermediate MyDotNetType which would take as a constructor argument Mytype (the COM object) and expose it out as a read-only property.
Then the MySub call, would take the MyDotNetType as an argument.
Kind Regards
Noel
Please check the signature of the Function in both base class and derived class, if you have different agruments or data type o any arguments is not matched. Then you'll get this type of error. Simple please check the function name, argument name and data type. It worked me. I hope this answer will be helpful.
Thanks,
Ramu V