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.
Related
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
I am building a VB.NET class library that will be used for VBA Projects. In my library, I have a module called "Globals" I wish to store some global (Library level) properties and methods in:
Imports System.Runtime.InteropServices
<ComVisible(True)>
Public Module Globals
<ComVisible(True)>
Public Const TestGlobal As Integer = 0
End Module
However, when I reference my library in the Excel VBE, my module shows up as a Class and I can't see my constant variable in the Object Browser:
What am I missing or doing incorrectly that's causing my module to show up as a class?
There's somewhat of an "impedance mismatch" between VB.NET and COM. COM works primarily with interfaces, and .NET builds the .tlb files from VB projects in a way that makes them more accessible to COM. A Module in VB.NET is basically just a static class in the managed world. When the interop assembly is built from your code, it sees a class, wraps it in an interface, and attaches the interface to the class:
Note that you can't provide your own interface implementation for a Module, because static classes in .NET can't implement interfaces.
The other thing that you can't do in .NET is create member procedures that aren't wrapped in a class. That is basically what a Module is in the COM world. For example, take a look at the IDL for the VBA Strings module:
module Strings {
[entry(516), helpcontext(0x000f665f)]
short _stdcall Asc([in] BSTR String);
[entry(537), helpcontext(0x000f6e9f)]
BSTR _stdcall _B_str_Chr([in] long CharCode);
[entry(608), helpcontext(0x000f64e2)]
VARIANT _stdcall _B_var_Chr([in] long CharCode);
[entry(517), helpcontext(0x000f6ea0)]
Note that all of the entries have a .dll entry point specified. That's basically because you're making raw function calls of the variety you'd find in the C world. If an analogue existed in the .NET world, it would be a Sub or Function declared at the namespace level instead of the class (or module) level...
<ComVisible(True)>
Namespace SomeClass.Functions
<ComVisible(True)>
Public Function Foo() As String
Return "Foo"
End Function
End Namespace
...which obviously isn't valid .NET code.
On a related note, keep in mind that you aren't seeing the entire picture in VBA either. VBA is basically built on top of COM, but it tries really hard to abstract away most of it. A VBA Module can for all intents and purposes be treated as a static class. For example, you can give them properties, public members, etc. At the end of the day, it really doesn't matter whether the VBA Object Browser sees something as a class, a module, or whatever - what matters is that you can use managed code from an unmanaged context. Just work around the differences in the 2 infrastructures to get something usable and call it a day:
Imports System.Runtime.InteropServices
<ComVisible(True)>
Public Enum Constants
GlobalOne = 0
GlobalTwo = 1
GlobalEtc = 2
End Enum
<ComVisible(True)>
Public Class FunctionProvider
<ComVisible(True)>
Public Function Foo() As String
'Note that the class doesn't need to keep track of "state" to be usable.
Return "Foo"
End Function
End Class
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.
Currently in a Win Form application, im using a Global Variable Class which contains variables that are used to to share data. My question is, what other ways are there to achieve this? Best practises? and why?
Globals are bad for many reasons, but probably the most glaring reason is because, ideally speaking, every time you call the same method, passing it the same parameters, it should always do the same thing with the same results. Globals brake that rule. Suddenly your code starts behaving in unpredictable ways because something wasn't initialized properly somewhere else, or some global got modified incorrectly.
The best way I've found to get rid of the need for globals is to adhere to the principles of dependency injection (DI). There is much material on the topic online, but in a nutshell, rather than having classes reach out to create or find their dependencies on their own, they should simply request that the dependencies be provided to them, often in the constructor. Anything that you are accessing via global variables would, by definition, be considered dependencies of the classes that access them. Therefore, instead of, for instance, having a global settings object, like this:
Global settings As New Settings()
And then a class that uses it like this:
Public Class MyClass
Public Sub DoSomething()
If settings.SomethingEnabled Then
' ...
End If
End Sub
End Class
You would instead, do it like this:
Public Class MyClass
Public Sub New(settings As Settings)
_settings = settings
End Sub
Private _settings As Settings
Public Sub DoSomething()
If _settings.SomethingEnabled Then
' ...
End If
End Sub
End Class
This makes your code much cleaner, more flexible, and more reliable. It also makes the code far more testable too, which is a great added benefit.
Data should be shared according to how it is going to be used. If a variable is required across the entire application then it can be seen to have global scope and a global variable concept (e.g. public static shared) may well be appropriate.
Often this is not the case however as global variables should really be avoided (check out here and here for more reasoning)
Data should be encapsulated at the level it is required - for example if a form has data / variables within it that are applicable to it's function but where other forms need to now the value, this would be the ideal case for a public readonly property on the form, which would mask the actual detail of the variable from the rest of the aplication.
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