Using StatePrinter from VB rather than C# to implement ToString - vb.net

I'm trying to follow the promising suggestion posted here to try StatePrinter as a shortcut to rolling my own ToString methods. I agree with the OP that it is a shame that VS still can't generate this method for me.
I've got a fairly large project, in VS2015 (Community Edition), with both VB and C# code. I added the current stable version of StatePrinter using NuGet.
I can make the example code from the SO answer work fine in my C# code but when I do what I think is the equivalent in my VB code:
Private Shared sp As StatePrinter.Stateprinter = New StatePrinter.Stateprinter
Public Overrides Function ToString() As String
Return sp.PrintObject(Me)
End Function
I just get the compiler error
'Stateprinter' is ambiguous in the namespace 'StatePrinter'
There IS another constructor, StatePrinter (note difference in capitalization only) which is deprecated and, in any case, generates the same error message.
I'm led to the unfortunate conclusions that
VB in VS2015 is acting as if it is case insensitive. Can that be true?
No one else is using StatePrinter from VB.
Can anyone provide any suggestions on how to use StatePrinter from VB? I'm willing to believe I'm making some rather brain-dead mistake in converting the C# example to VB.

It is near impossible to use this directly in VB and get around the ambiguous name issue. You could write a class library wrapper in C# that doesn't expose this mismatch (that is, it has an internal StatePrinter object and exposes constructors that are PascalCased the same.
Another option would be to use reflection in the VB project to get around the case insensitivity.
You could also create a GitHub issue. Or, be a contributor to the project and create a suggested fix for it. :)

As soon as I got done writing #1 in the question above, I was able to figure out how to search for the answer to that bit.
Yes, VB is case insensitive, at least, as far as it needs to be in this case:
See the rather nice writeup here:
https://stackoverflow.com/a/2301980/165164
So, we're left with the rather plaintive: is no one else using StatePrinter from VB?

Related

Ironpython - Issues attaching to an instance of an already running program

Ok folks this is a long one, so please bear with me. I'll preface this by stating that I am -for all intents and purposes- a noob.
I'm trying to link to a running instance of a program (ETABS) using IronPython. The program has an API and decent documentation on how one can go about hooking into the running instance (EXAMPLE). However, their examples are for Python, C#, VB.net but not IronPython.
No biggie I thought, the Marshal module can be used to hook into it. So I tried this:
from System.Runtime.InteropServices import Marshal
csiApp = Marshal.GetActiveObject("CSI.ETABS.API.ETABSObject")
SapModel=csiApp.SapModel
Unfortunately I get errors on that last line - "ETABSObject has no attribute SapModel".
And yes, I've tried running it with csiApp.SapModel() as well with the same results.
So I delved deeper into it and apparently the object needs to be cast into another type - at least that's the way its been done for the C# example (LINK). Since - to my knowledge - we can't really cast objects around in Python (and yes, I've already tried clr.Convert) I came to the conclusion that the object being returned to Ironpython is a few abstractions removed from the object that I really need. Apparently comtypes can handle this automatically in the background (seeing as the python example works flawlessly). The code block below shows the object types returned to Ironpython and to pure python respectively:
Ipy : <System.MarshalByRefObject object at 0x000000000000002B [CSI.ETABS.API.ETABSObject]>
Python with comtypes : <POINTER(cOAPI) ptr=0x2e68d17f7c8 at 2e690b36a48>
I'm working on Ironpython 2.7.3 and can't really update it (for several reasons not relevant to this post). Would love to have advice on how to fix this or on how to install comtypes on Ipy.
So I think I've found the reason why this is happening - Ironpython cannot directly use MarshalByRefObjects (source) since Reflection doesn't work on these. It seems I'll need to create a C# class which can cast this object into the one I want, compile it into a dll and load that into my Ipy code.
I'll leave this here in case someone with more knowledge has a better answer.

Conditional Compliation Constant VB

Error BC31030 Conditional compilation constant '; ^^ ^^ EXCLUDE_CODEGEN' is not valid: Identifier expected. GpsHost C:\Projects\GpsTrackSolution\GpsHost\vbc 1 N/A
I am getting the above error when I try and build a VB.NET win forms app. I refactored it a little, updated to framework 4.7.2 and now I am getting this.
There is NO reference in ANY vbproj for that string of characters, either partial or full. I've done a find in file contents across the entire solution and cannot find that anywhere. Almost at my wit's end as to what could be doing this.
This was unrelated to VB, it was actually due to Orleans code generation trying to insert constants. Orleans isn't really designed to work with VB, so I switched to runtime codegen, instead of build time, and it worked.

Visual Basic lack of parenthesis for functions identification

Any way to have any sort of identification for the lack of parenthesis for functions with no parameters at VB?
I have found this answer, but since it is 9 year old, i hope a solution exists now.
I am using Visual studio 2017. I have strict mode on. I have checked format settings available for Visual Studio and found no relative option. I have checked project settings as well.
Edit:
I have noticed that when i type a new function name that it does add parenthesis, could this be triggered somehow?
You are not going to find what you need built into the compiler or project settings, because the optional parenthesis are build into the VB.Net language specification and the compiler will compile according to that specification. Now one thing you might want to consider is running your code through a VB.Net to C# Converter, then running that converted code through a C# to VB.Net converter. For example, consider this VB.Net code:
Sub Main
Foo
End Main
If you run this through Telerik's code converter, it produces this C# code:
public void Main()
{
Foo();
}
Now if you take that C# code and convert it back into VB.Net using Telerik's code Converter, it produces this Vb.Net code:
Public Sub Main()
Foo()
End Sub
Notice how it added the parenthesis to the Foo method. This technique might work for you, if your code isn't too complex.

Len() function vs String.Length property; which to choose?

I'm making the transition from VB6 to VB.Net (VS 2010) and have a basic rather than expansive understanding of the latter. I obviously have quite a bit of code to... I hesitate to use the word "upgrade" when "port" would be more apt given that the upgrade wizard in past versions of VS may as well have just commented out the code and said "Hey, why don't you re-start from scratch?"
In one procedure which I'm bringing across the Len() function was used to determine the length of a string variable. That still works in VB.Net (though I imagine that it's actually a call to the Strings.Len Method), but the other alternative is to just query the .Length property of the variable.
The question is which to use and why. I've looked through the relevant MSDN pages and all they seem to tell me is that the method/property exists. Nothing is said about performance issues, particularly when loops of large numbers of calls might be involved.
My question, then, is whether anyone is aware of any tested and confirmed benefit of using one approach over the other, or whether it's merely a question of personal preference. Any pointers on similar situations that I might encounter as I make the progression would also be appreciated though given the Stack Overflow guidelines it's just this one issue that I'm interested in seeing whether there's a specific answer to.
Because you're using VB.NET, your Strings can be Nothing and unless you explicitly check for that, most VB methods, including Len, will treat it the same as String.Empty i.e. "".
With Reflector you can see Len is implemented as a null check, returning 0 for Nothing and otherwise returning .Length, and the JITter will likely in-line the call.
So, if you're using other VB methods, I'd suggest using Len too, unless you know the String is not Nothing or check for Nothing everywhere.
So according to this:
Len, another classic BASIC function, returns the length of a string. System.String has the Length property that provides the same information. Is one better than the other?
Performance-wise, these two functions show little difference over 1000’s of iterations. There doesn’t appear to be any reason to prefer one over the other in this case plus there is no functional difference. I’m kind of partial to using the property value rather than the VB function since it encourages thinking of .NET strings as objects. However, at the core, it’s really only a personal preference thing.
If you trust their word, then there's your answer. Otherwise, coding up a test and iterating should give you the final answer.
I'm not sure about the specifics of the Len() method (my language of choice is C#), but I would say definitely go with the Length property. Length is a member of the System.String class, whereas Len() isn't.
My guess is that Len() is just a VB shim on top of the Length property. Someone could probably make the argument that using Len() is more idiomatic, from a VB point of view. I think I'd prefer to use the property built in to the class, rather than just use a different mechanism just because it's provided by the language.
The Len method is provided for backwards compatibility with old VB6 (and earlier) non-.NET code. There's nothing technically wrong with using it. It will work, and just as well, at that. But, it's better to use the new .NET way of doing things whenever possible. Outside of getting you more into the ".NET mindset", though, the only real tangible benefit of using String.Length is that it makes it easier to port the code to other .NET languages in the future.
In addition to #Andrew's post, the Len() is string function from Visual Basic run-time library where as Length is a property of System.String class of .net framework API.
Recently I faced problem with my old VB.Net code that was using Len() function. I upgraded my project to Core which was referencing the old VB.net dll file and it was using Len() function. I got run time compatibility error - Method not found: 'Int32 Microsoft.VisualBasic.Strings.Len(System.String)'
I have to change all such old function that Core has deprecated. So I stand by using String.Length over Len() as suggested by Steven Doggart.

Is use of Mid(), Instr(), LBound(), UBound() etc. in VB.Net not recommended?

I come from a C# background but am now working mostly with VB.Net. It seems to me that the above functions (and others - eg. UCase, LCase) etc. are carryovers from VB6 and before. Is the use of these functions frowned upon in VB.Net, or does it purely come down to personal preference?
My personal preference is to stay well away from them, but I'm wondering if that is just my C# prejudice.
I've come across a couple of issues - particularly with code converted from VB6 to VB.Net, where the 0 indexing of collections has meant that bugs have been introduced into code, and am therefore wary of them.
The reason that those functions are there in the first place is of course that they are part of the VB language, inherited from VB 6.
However, they are not just wrappers for methods in the framework, some of them have some additional logic that makes them different in some ways. The Mid function for example allows that you specify a range that is outside the string, and it will silently reduce the range and return the part of the string that remains. The String.Substring method instead throws an exception if you specify a range outside the string.
So, the functions are not just wrappers, they represent a different approach to programming that is more in line with Visual Basic, where you can throw just about anything at a function and almost always get something out. In some ways that is easier, as you don't have to think about all the special cases, but on the other hand you might want to get an exception instead of getting a result when you feed something unreasonable to a function. When debugging, it's often easier if you get the exception as early as possible instead of trying to trace back where a faulty value comes from.
Those options are for backward compatibility.
But, it will be better for people to use framework classes/methods to ensure consistency.
Having said that, VB6 functions are easy to understand. So, it should not be an issue for someone who has the VB background.
EDIT: Also, some of the overloads available with framework classes, might not be available with an equivalent of a simple VB6 like statement. I cannot remember of any, as of now - But this is what I think, could be a better reason to use framework classes/methods.
There will be special cases, but, Hands down, use the VB6 versions, unless you care about the difference between a string being "" and Nothing.
I was working on a big project where different programmers using both ways, the code where people used MyString.SubString(1) was blowing up while Mid(MyString,2) was working.
The two main errors for this example: (Which apply in various ways to others as well)
(1) String can be nothing and you have to check before running a method on it. Limitation of the OO notation: You can't call a member method if the object is nothing, even if you want 'nothing' or (empty object) back. Even if this were solved by using nullable/stub objects for strings (which you kind of can using "" or string.empty), you'd still have to ensure they're initialized properly - or, as in our case - convert Nothing to "" when receiving strings from library calls beyond our control.
You are going to have strings that are Nothing. 90% of the time you'll want it to mean "". with .SubString, you always have to check for nothing. With the VB versions, only the 10% about which you'll care.
(2) Specifically with the Mid example, again, 90% of the time if you want chars 3-10 of a 2 char string, you'll want to see "" returned, not have it throw an exception! In fact, you'll rarely want an exception: you'll have to check first for the proper length and code how it should behave (there is usually a defined behaviour, at the very least, a data entry error, for which you don't want to throw an exception).
So you're checking 100% of the time with the .Net versions and rarely with the VB versions.
.Net wanted to keep everything into the object-oriented philosophy. But strings are a little different than most objects used in subtle ways. MS-Basic wasn't thinking about this when they made the functions, it just got lucky - one of the strengths of functions is that they can handle null objects.
For our project, one may ask how Nothing strings got into our flow in the first place. But in the end, the decision of some programmers to use the .Net functions meant avoidable service calls, emergency bug fixes, and patches. Save yourself the trouble.
I would avoid them. Since you've mentioned them it sounds as though you've inherited some VB6 code that was possibly converted to a VB.NET project. Otherwise, if it was a new VB.NET project, I see no value in using the VB6 methods.
I've been on a few VB6 to VB.NET conversion projects. While I am familiar with the names and the difference in 0 based indexing, any code I came across got refactored to use their .NET equivalents. This was partially for consistency and to get the VB6 programmers on that project familiar with the framework. However, the other benefit I've found in refactoring is the ability to chain method calls together.
Consider the following:
Dim input As String = "hello world"
Dim result As String = input.ToUpper() ' .NET
Dim result As String = UCase(input) ' VB6
Next thing you know, I need to do more work to satisfy other requirements. Let's say I need to take the substring and get "hello," which results in the code getting updated to:
Dim result As String = input.ToUpper().Substring(0, 5) ' .NET
Dim result As String = Mid(UCase(input), 1, 5) ' VB6
Which is clearer and easier to modify? In .NET I just chain it. In VB6 I had to start at the beginning of the method, then go to the end of it and add the closing parenthesis. If it changes again or I need to remove it, in .NET I just chop off the end, but in VB6 I need to backtrack to the start and end.
I think there's value in using the .NET methods since other .NET developers that join the project later, especially those from a C# background, can easily pick it up.