ToString vs. ToString() in VB.NET - vb.net

What is the difference between using ToString and ToString() in VB.NET?

Nothing. VB.NET allows you exclude the parentheses on any method that doesn't take in an argument.

The existing answer is wholly correct but does not cover when ToString is used as a Method. This is essentially incorrect coding but it is possible
Dim sbrBuilder as New StringBuilder
...
sbrBuilder.ToString()
return sbrBuilder.ToString
The first ToString (which does nothing) does not produce an error but the brackets are forced on by the IDE. The second ToString does not require brackets (optional - as explained already in the Answer) as it is used to collect the value of ToString.
Hopefully this will help anyone who is wondering why the IDE keeps adding brackets on ToString - then you will realise that you forgot to assign it to anything like I did

Related

Why does this simple string formating now throw exception?

I'm using Authorize.net API and they require card expiration field to be formated as "yyyy-mm". We did that with this simple line of code:
expirationDate = model.Year.ToString("D4") & "-" & model.Month.ToString("D2")
and this absolutelly worked. I still have cards stored in the system that were saved using this method! But today I was testing something completelly unrelated, and wanted to add another card, and bam, this code exploded with this exception:
System.InvalidCastException: 'Conversion from string "D4" to type 'Integer' is not valid.'
Inner exception to that one is:
Input string was not in a correct format.
This just... doesn't make sense to me. Why in the world is it trying to convert format specifier (D4) into an integer? What input string? What in the world changed in two days?
The problem is that your are using a Nullable(Of Integer). This is a different structure that does not support the overloads of the ToString method a normal Integer has.
You can view the overloads of the Nullable structure here.
I suggest you use the GetValueOrDefault() method to get the proper Integer and also apply the value you expect in case the value is Nothing.
If it is impossible that a instance with a Nothing set for the year reaches this method you can simply use the Value property.
I still do not fully understand why you get this strange error message. Maybe you could check out what the actual method that is called is? Pointing at the method should give you that information. It can't be Nullable(Of Integer).ToString
Well, I found a workable solution and something of an answer thanks to #Nitram's comment. The type of Year/Month property has been changed from Integer to Integer?. Obviously, this isn't a very satisfying answer because I still don't understand why the nullable int can't be formatted, and yet the code compiles perfectly. The working solution for me has been using static format method on String as so:
expirationDate = String.Format("{0:D4}-{1:D2}", model.Year, model.Month)
This works fine even with nullable types.

String template to set the default value of PARAMETER

Is it possible, in ABAP, to evaluate string templates dynamically?
Normally, you will have some string template in code that will be checked by the compiler. (The variables in the curly brackets are checked by the compiler at compile time).
However, is it possible to have a string evaluated at runtime?
So, instead of:
data(val) = |System ID: { sy-sysid }|.
I would like the string to be interpolated to come from elsewhere, for example:
parameter: p_file type string lower case default '/mnt/{ sy-sysid }/file.txt'.
In this case, I would like to have the value of p_file to be evaluated at runtime to substitute the variable (sy-sysid) with the runtime value.
You could, of course, program your own substitution by finding all occurrences of variables with curly brackets with a regex expression, then evaluate the variable values with ASSIGN and substitute them back into the string, but I am looking for a built-in way to do this.
Sorry, this is maybe a stupid example, but hopefully you understand what I mean. (If not, please let me know in the comments and I will try and clarify).
The problem in your snippet is not with string template but with PARAMETER behavior. It does not allow dynamics in DEFAULT clause.
To achieve what you want you should use INITIALIZATION and set path value in runtime:
parameter: p_file type string lower case.
INITIALIZATION.
p_file = | /mnt/{ sy-sysid }/file.txt |.
Unfortunately, the example you gave, does not make any sense to me. ABAP String templates are evaluated at run-time and type-checked at compile-time.
In your example, it is always the run-time value of SY-SYSID that will be written to the variable.
I guess what you want to do is circumvent compile-time checks for expressions inside a string template.
Please try to give us your actual use case, so maybe we find an even better solution to your problem.
However, here is what I think could help you:
Personally, I do not recommend to write code like the one below, because it is extremely error-prone likely to mislead other programmers and because there is very likely a better solution.
Given that you know the name of a variable at run-time, try this:
".. say LV_VARNAME is a charlike variable that contains a
" variable name at runtime.
"NOTE that the variable LV_VARNAME must be visible in the scope of the
"following code.
FIELD-SYMBOLS: <my_var> TYPE any.
ASSIGN (lv_varname) TO <my_var>.
DATA(lv_str) = |The value is { <my_var> }|.

Why am I getting 'Trim' is not declared with this VB.NET code?

I am trying to get a VB.NET app to compile. Besides the "elephant in the room", I'm also getting 7 "'Trim' is not declared" errors on code like this:
...as well as one "'IsNothing' is not declared. It may be inaccessible due to its protection level." on this line:
If IsNothing(memberList) = False Then
I don't know VB, so there may be a simple solution to this, but I have no clue what the problems are.
The Trim function requires a reference to Microsoft.VisualBasic from the assembly Visual Basic Runtime Library (in Microsoft.VisualBasic.dll)
Usually is preferable to use the native Trim method from the string class and not add a reference to this assembly (mainly used to help porting old VB6 apps)
mail.CC.Add(addr.Trim())
Notice also that the string.Trim removes other whitespace characters as tabs while the Microsoft.VisualBasic function does not.
You have to use addr.Trim instead of Trim(addr)
Read more about Trim in this MSDN article
And you should use
If not memberList Is Nothing Then
Instead of
If IsNothing(memberList) = False Then
Or
You have to import Microsoft.VisualBasic namespace
If you use the Left(), Mid(), and Right() string functions you might find it easier to convert those too:
Left(t, l) becomes t.Substring(0, l)
Mid(t, s, l) becomes t.Substring(s-1, l)
Right(t, l) becomes t.Substring(t.Length - l)
Often Left and Right are properties and stop you using the old VB string functions.
String.Trim doesn't take a string parameter. It returns a new string in which all leading and trailing occurrences of a set of specified characters from the current String object are removed.
It should be...
addr.Trim()

Write String.Join(Of T) in VB.Net

I have a simple code in C#:
Console.WriteLine(string.Join<char>("", ""));
And I can't convert it to VB.Net. Even reflector show me code in VB like:
Console.WriteLine(String.Join(Of Char)("", ""))
But it can't be compiled becouse I have an starge error:
Error 1 Expression expected.
It looks like VB.Net don't have this generic method at all.
Both project use Net Framework 4.
Why this error happened?
UPD:
I've create a custom class and copy Join(Of T) declaration to it:
Class string2
Public Shared Function Join(Of T)(ByVal separator As String, ByVal values As System.Collections.Generic.IEnumerable(Of T)) As String
Return "1"
End Function
End Class
Console.WriteLine(string2.Join(Of Char)("", ""))
It works
UPD2:
My compilation string, where you can see that I'm using Net4:
http://pastebin.com/TYgS3Ys3
Do you have a code element named String somewhere in your project?
Based on the answer you have added to this question (where you indicate that changing String to [String] appears to have solved the problem), I guessed that this may be the result of a naming collision.
I was able to duplicate the error you are seeing -- "Expression expected" -- by adding a module to my project called String and defining a (non-generic) Join method from within that module.
This may not be the specific scenario you find yourself in. But the fact that the code works for you with [String] is, to me, very compelling evidence of a simple namespace collision.
Based on the documentation for the "Expression expected" error, I'm guessing you haven't included the entire section of code where this error is appearing for you.
Do you have a lingering operator such as + or = somewhere?
(The VB.NET code you posted is indeed equivalent to the C# code above it and should compile no problem. This is why I suspect the real issue lies elsewhere.)
String.Join<T>(string, IEnumerable<T>) is useful with LINQ, for standard joins is better to use the String.Join(string, string()) overload.
In C#, "" as Char produces an empty Char (\0). Writing the same thing ("") in VB produces an empty string which is not the same as an empty char. In order to produce an empty character, you'll have to write New Char().
Your VB code therefore becomes:
Console.WriteLine(String.Join(Of Char)(New Char(), New Char()))
Edit
I just checked and it appears String.Join does not support the format you're specifying.
Instead, it goes as follows:
Join(separator As String, value As String()) As String
Your code should be as follows:
Console.WriteLine(String.Join("", New String() {""}))
String.Join(Of Char)(str1, str2) wasn't added til .net 4, it seems. That's why your custom class worked -- it had the declaration, but the String class in the framework you're actually using doesn't.
Check your settings and references to make sure you're targeting .net 4 all around -- cause that's the only thing that seems able at this point to stop the call from working.
Here the solution:
Console.WriteLine([String].Join(Of Char)("", ""))
Why this problem occurs only with generic method? I wish I know...

How Do I Create Something 'OF' a Variable's Type?

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.