How do I declare "as any" in VB.NET, or what is the equivalent?
The closest you can get is:
Dim var as Object
It's not exactly the same as VB6's as Any (which stores values in a Variant) but you can store variables of any type as Object, albeit boxed.
VB.NET does not support the as any keyword, VB.NET is a strongly typed language, you can however (with .NET 3.5) use implicit typing in VB
Dim fred = "Hello World" will implicitly type fred as a string variable. If you want to simply hold a value that you do not know the type of at design time then you can simply declare your variable as object (the mother of all objects) NOTE, this usually is a red flag for code reviewers, so make sure you have a good reason ready :-)
As Any must be referring to Windows API declarations, as it can't be used in variable declarations. You can use overloading: just repeat the declarations for each different data type you wish to pass. VB.NET picks out the one that matches the argument you pass in your call.
This is better than As Any was in VB6 because the compiler can still do type-checking.
I suppose you have problems with converting WinAPI declarations. Sometimes you can get away if you just declare your variable as string or integer because that is the real type of value returned.
You can also try marshaling:
<MarshalAsAttribute(UnmanagedType.AsAny)> ByRef buff As Object
VB.NET doesn't support the "As Any" keyword. You'll need to explicitly specify the type.
Related
Background: I've got a set of VB6 DLLs that share a common "interface". Whichever version is installed locally has members of this interface invoked via COM interop (from VB.Net code, which I suspect might matter). I noticed today that one of the invocations passes [what I understand to be] an rvalue (hereinafter "an rvalue") to a VB6 function that does not have that particular parameter defined as ByVal.
Example Code:
VB6:
Public Function VB6Function(input As String) As String
' Do interesting things with input
End Function
VB.Net:
' get an instance of the VB6 class and pass our trimmed localString to it
result = vb6Instance.VB6Function(localString.Trim())
' Do interesting things with localString
I have not yet noticed an instance of the VB6 code changing the value of input, but I also haven't done an exhaustive search of the different DLL implementations (there are several hundred).
What would happen if VB6Function did change the value of input when input is "an rvalue"? For that matter, why doesn't this method invocation simply error out when "an rvalue" is passed?
What would happen if VB6Function did change the value of input when input is "an rvalue"?
Nothing. Or rather, nothing interesting.
When the called function changes the value of its argument, it makes no difference for the insides of that function whether the argument was provided byval or byref. All that matters is that there is a variable of certain type, thus, it can be acted upon.
For that matter, why doesn't this method invocation simply error out when "an rvalue" is passed?
Why would it error out? The passed argument as correct type (string), that is all that matters.
There is no notion of an rvalue in VB.
When you pass what you would call an rvalue to a method accepting something by reference, the compiler automatically passes the reference to a temporary location where the rvalue actually resides. The method gets its value byref, the caller does not care about pointers.
localString.Trim() allocates and returns a string. It has an address and can be passed around. Your code does not explicitly capture that address, but the compiler has no problem passing it to VB6Function byref. If VB6Function changes the value, it changes what that temporary location points to, which has no observable difference because it's going to be destroyed after the call either way.
As for why some people may have preferred receiving strings byref in VBA, it's specifically to avoid copying the entire string each time when calling the function. In VB.NET it's not a problem because strings there are immutable and therefore can be passed byval without copying, but in VBA that is not the case, so a byval string needs to be cloned for the purpose of the call. People avoided that by specifying byref, even though that technically gave them the power to mess with the passed variable.
I'm writing some code in Visual Basic 6 and I have noticed that I don't even need to declare variables for things to work.
The following (explicit declaration):
Dim foo As String
foo = "Bar"
Seems to work just as well as this (implicit declaration):
Dim foo
foo = "Bar"
Or this (no declaration):
foo = "Bar"
I know in C# I need to declare a variable before I use it, and that implicit and explicit declarations are both acceptable. I also know that in Python, you don't declare your variables at all before you use them.
In regards to Visual Basic 6 (and by extension VBA) which is proper?
Thanks
It's a good HABIT.
There is a VB option called Option Explicit. With that set to ON, then VB forces you to declare a variable before you use it: no more
foo = "Bar"
That helps with mistyping the variable name later in your code... without that, you can typso the variable name, your program compiles but won't work, and it's HARD to dig that out.
In Tools/Options, Editor tab, check the Require Variable Declaration checkbox. This will automatically add Option Explicit to every new code module.
I would say this is more than a best practice; I think of it as a requirement for programmer sanity. The setting is persistent; once set, it stays enabled. Microsoft made it an option because some older versions of VB didn't have the feature, which also explains why it was disabled by default.
Should I explicitly declare my variables in VB6?
Yes. Why?
Not just because it is a good habit or it is a must but because of only one main reason which I have mentioned in this post as well.
VB defaults the variable to being type Variant. A Variant type
variable can hold any kind of data from strings, to integers, to long
integers, to dates, to currency etc. By default “Variants” are the
“slowest” type of variables.
AND
As I mentioned earlier, If you do not specify the type of the
variable, VB defaults the variable to being type Variant. And you
wouldn’t want that as it would slow down your code as the VB Compiler
takes time to decide on what kind of variable you are using. Variants
should also be avoided as they are responsible for causing possible
“Type Mismatch Errors”.
Topic: To ‘Err’ is Human (See Point 3)
Link: http://siddharthrout.wordpress.com/2011/08/01/to-err-is-human/
The above link also covers other parts related to coding that one can/should take care of.
HTH
I highly reccomend that you always declare your variables. This can be forced by setting Option Explicit in each code module. You can let VB6 do that automatically for you by going to Tools->Options, in the Editor tab check Require variable declaration.
If you don't use Option Explicit, then a variable will be automatically created for you each time you reference a previously unknown variable name. This is a very dangerous behavior, because if you mistype a variable name, an empty variable will be created for you, causing unexpected behavior of your code.
You don't have to declare the type of your variables but I would also recommend that you do that. The default type of a variable is Variant, which has a small performance overhead and create some problems if you are creating COM objects for use by C++ or C# (if anybody does that anymore).
I'm developing a vb.net program with VS2008. In my case, dt_list is a instance member as List(of Single). When I wrote
dt_list = CType(ser2.Deserialize(r), dt_list.GetType())
VS2008 complains about "Type 'dt_list.GetType()' is not defined.".
Why? Thanks in advance.
The reason this is not allowed is that the exact value of the type for GetType() must be determined at runtime. The second parameter of CType can only be an "expression that is legal within an As clause in a Dim statement, that is, the name of any data type, object, structure, class, or interface", for instance, List(Of String), which can be determined at compile time.
The following is accordingly legal:
dt_list = CType(ser2.Deserialize(r), List(Of Single))
EDIT:
Casting to an arbitrary type, where the type is not known at compile time, is more involved, however. The proposed answer to this question in the MSDN Forums shows one approach. Though it's in C#, I will guess the same approach can be used in VB.NET as well.
What are you trying to achieve by selecting the cast type at runtime?
You may be able to solve your problem with an interface.
Dim dt_list As IList = Ctype(ser2.Deserialize(r), IList)
This gives you access to all of the List members in IList.
I have some code like:
Lookup(Of String)("Testing")
Lookup(Of Integer)("Testing")
And both of those Lookups work great. What I'm trying to is call the appropriate LookUp based on the type of another variable. Something that would look like...
Lookup(Of GetType(MyStringVariable))("Testing")
I've tried to Google this but I'm having a hard time coming up with an appropriate search. Can anyone tell me how to do what I want?
You do not specify the full signature for the method that you're calling, but my psychic powers tell me that it is this:
Function Lookup(Of T)(key As String) As T
And you want to avoid having to repeat Integer twice as in the example below:
Dim x As Integer
x = Lookup(Of Integer)("foo");
The problem is that type parameters are only deduced when they're used in argument context, but never in return value context. So, you need a helper function with a ByRef argument to do the trick:
Sub Lookup(Of T)(key As String, ByRef result As T)
T = Lookup(Of T)(key)
End Sub
With that, you can write:
Dim x As Integer
Lookup("foo", x);
One solution to this is to use reflection. See this question for details.
You can't use a dynamic type unless you do runtime compiling, which of course is really inefficient.
Although generics allows you to use different types, the type still has to be known at compile time so that the compiler can generate the specific code for that type.
This is not the way to go. You should ask about what problem you are trying to solve, instead of asking about the way that you think that it should be solved. Even if it might be possible to do something close to what you are asking, it's most likely that the best solution is something completely different.
The VB.NET compiler in VS2008 actually uses type-inference. That means if you are using a generic method, and one of the parameters is of the generic type, then you don't need to specify the generic type in your call.
Take the following definition...
Function DoSomething(Of T)(Target As T) As Boolean
If you call it with a strongly-typed String for Target, and don't specify the generic parameter, it will infer T as String.
If you call it with a strongly-typed Integer for Target, and don't specify the generic parameter, it will infer T as Integer.
So you could call this function as follows:
Dim myResult As Boolean = DoSomething("my new string")
And it will automatically infer the type of T as String.
EDIT:
NOTE: This works for single or multiple generic parameters.
NOTE: This works also for variables in the argument list, not just literals.
I would like to ask humbly to those vb.net experts out there regarding optimization of the code. My example here is
a.
Dim lblEventCategory = CType(Me.gvSpecialEvent.Rows(e.NewEditIndex).FindControl("lblEventCategory"), Label)
b.
Dim lblEventCategory As Label = CType(Me.gvSpecialEvent.Rows(e.NewEditIndex).FindControl("lblEventCategory"), Label)
Which of the two is more efficient is it letter A? or letter B?
Can somebody help me understand these codes?
Thanks in advance
if we are talking .Net 3.5 than what 1800 INFORMATION says is not true since type inference will take place and the compiler will infer the type and hence be typesafe.
so in .Net 3.5 a and B are the same.
In Visual studio 2008 just turn Option Infer On or Off to see the difference.
Before .Net 3.5 no type inference will take place and it will use the variant type or rather the object type.
So in pre.Net 3.5 A and B are not the same.
In .NET 3.5 Dim x = value is the same as C# var x = value; The compiler will infer the type so both are equal at runtime.
The first one defines the variable lblEventCategory as a Variant type. This is generally worse than the second where you use an explicit type. The Variant type is a kind of "catch all" that can safely hold any type of variable, but you lose any and all type safety and warnings that the compiler might have been able to give you. Also a Variant type uses more memory and will be slower at run time because of the conversions that need to be performed on it.
Additionally, method calls will be "late bound" - this means that the calls to those methods will not be resolved until runtime, when the type of the variable is known, the call is then made by name. This is typically astronomically slower than if you use the explicit type where the call can be made "early bound" (i.e., at compile time).
On the other hand, Variant types do have their place. They are useful in OLE automation (COM) programming, if you are interacting with a language like VBScript that only supports variant types. In that situation, you may be wise to wrap the calls into the late-bound code so that the Variant type is converted to and from the correct type at the boundary of the call.