I used developerfusion.com to convert a snippet of my C# code to VB .NET and I noticed the String type translated into [String].
I tried Google and Searching SO to no avail so I will ask the community is there a difference between [String] and String? And if so what is/are the difference(s)?
In VB.Net, the [] surrounding a word is used to allow a keyword to be used as a normal identifier. So using [String] means I want to identify something with the word String and not the VB keyword String.
The converter probably did that because it didn't recognise the string type and thought that it was a class defined in your code.
You can put brackets around identifiers to use keywords. You could create your own [String] class that would be different from the built in String class, but that could of course easily get confusing...
Public Class [String]
Public Value As Integer
End Class
Dim s As New [String]
s.Value = 42
Brackets usually indicate a variable name that using a reserved keyword. Did you name string variables String?
Brackets can be used in VB.NET to allow VB.NET keywords to be used as user defined names. For example, you could create a class called Integer, even though there is already an Integer keyword in VB.NET:
Public Class [Integer]
End Class
Hope this clarifies!
Related
I was reviewing some of my colleagues vb.net code the other day and was mystified at a new level - Unfortunately I don't have the code at hand but it looked something like this:
Public Class foo
Public Function [new]([bar] As String, [baz] As String) As String
Return String.Concat([bar], baz)
End Function
End Class
I have never seen these sharp parenthesis surrounding the name of the function and variable. Anyone can explain to me what the purpose of this is.
It's because "new" is a keyword and using [ ] is telling the compiler that it should read the keyword as a literal string instead. This way you can use keywords as variable and method names ... if you wanted.
I think the usage around the variables [bar] and [baz] is just .... well, because he could.
As a summary: I'm trying to get String.Concat to use a reference type's ToString overload when sticking string together.
Edit: Added this overview: The example code below is a cooked down extract of my real code - as such it would be immediately obvious when refactoring if I only had two lines of code. The important issue here (to me) is that I changed from a string to an object and there was no compile error from String.Concat. Equally it's behaviour wasn't what I would have expected (Using my object's to string method, rather than the bog standard object name). If I'd been using "&", there would have been a compile error. I'm concerned that the String.Concat syntactic sugar may lead to bugs that otherwise would have been avoided (in this case when refactoring). I'd like to know if there's a way of altering the behaviour of String.Concat or if I should consider it to be dangerous.
The situation:I've got a solution which processes a whole heap of data; I was using a String to contain the identifier of each piece of data, but have just swapped this out for a class (FeatureIdentifier) to enable me to extend the identifier to include things like batches etc.
I've refactored my code so that I use this class instead of just the string. When refactoring this type of thing (rightly or wrongly) I tend to rely on compile errors as a to-do list.
Now, I'm a self-taught programmer and I'm probably a bit set in my ways (I tend to look at new features in terms of if they let me do anything new rather than if they let me do stuff I can already do only easier) and I've just come across something which makes me sad.
So, I was sticking my identifier onto an underscore onto a type. My code looked like this:
Dim x as string = "MyIdentifer"
dim myOutputValue as string = String.Concat(x,"_ANCHOR.txt")
Running this I got myOutputValue equal to "MyIdentifier_ANCHOR.txt". Following refactoring, my code looked like this:
Dim x as new FeatureIdentifier("MyIdentifier")
dim myOutputValue as string = String.Concat(x,"_ANCHOR.txt")
Running this I got myOutputValue equal to "MyNamespace.FeatureIdentifier_ANCHOR.txt".
Having kicked myself and implemented a ToString method on my class, I run it again and get exactly the same output (that is "MyNamespace.FeatureIdentifier_ANCHOR.txt"). In immediate, if I do: ?x.ToString, I get "MyIdentifier", so I'm certain I've implemented ToString correctly.
So, here's my problem. I like the syntax of String.Concat but I don't like the fact that it doesn't do one of:
a) calling ToString on reference types it sticks together orb) throwing a compile error if you pass it non-string based arguments. The old school: x & "_ANCHOR.txt" gives me a compile error (which I would have picked up when refactoring).
Here's what I've tried:
I've tried shadowing the String.Concat function with an extension (something like this:
<System.Runtime.CompilerServices.Extension()> Public Function Concat(...some arguments...) As String
Return String.Concat(...some arguments...)
End Function
) but hit two problems:
1) When trying to narrow the type of the arguments down to string to cause compile errors, I realised that the argument is a param array and hence objects in the first place. So fail there.
2) When I tried to make multiple overloads ((s1 as string, s2 as string), (s1 as string, s2 as string, s3 as string) etc), I felt it was a bit lame and also discovered that you can't actually overload an extension on a static class (which is what I guess String is).
So, does anyone know a way of getting String.Concat to behave as well as old-school concatenation, or should I avoid String.Concat in favour of old-school concatenation?.
(I'm not going to use a StringBuilder, as I'm only concatenating a few strings and I don't believe this is the place for one).
I don't believe there is any way that you are going to "fix" the String.Concat method to only allow strings. Chalk it up to another reason why shared methods should be created and used as sparingly as possible. However, through the miracle of operator overloading, you can make your custom class work just like a string. To fix the Concat method, you need to overload the CType operator. To fix the string concatenation operator (&), you need to overload that operator separately, like this:
Public Class FeatureIdentifier
Public Sub New(id As String)
Me.Id = id
End Sub
Public Property Id As String
Public Property SomethingElse As Integer
Public Overloads Shared Widening Operator CType(value As FeatureIdentifier) As String
Return value.Id
End Operator
Public Overloads Shared Operator &(value1 As FeatureIdentifier, value2 As String) As String
Return value1.Id & value2
End Operator
Public Overloads Shared Operator &(value1 As String, value2 As FeatureIdentifier) As String
Return value1 & value2.Id
End Operator
End Class
Now you can use it like this:
Dim x As New FeatureIdentifier("MyIdentifier")
Dim myOutputValue As String = String.Concat(x, "_ANCHOR.TXT")
Or like this:
Dim x As New FeatureIdentifier("MyIdentifier")
Dim myOutputValue As String = x & "_ANCHOR.TXT"
And it will work just like as if it were still a string, in those circumstances. You may also want to overload some of the other operators too, just in case. For instance, the + operator also concatenates when applied to two strings. However, I should caution you that operator overloading can cause confusion to people who are not familiar with the code, since it works unexpectedly, so you should only use it if it really makes sense to do so.
Do you need to override ToString and even make sure it's called for this? It would seem to be more proper to expose a property of FeatureIdentifier named Identifier, or some such thing, and then you can just do:
Dim myOutputValue as string = String.Concat(x.Identifier, "_ANCHOR.txt")
Can someone please fill in the blanks for me, including a brief description of use and perhaps a code snippet? I'm well aware of the top two in particular, but a little hazy on the last one especially:
() - Used for calling a function, object instantiation, passing parameters, etc.
{} - Used for defining and adding elements to arrays or sets.
[] - Used for forcing an object to be treated as a type rather than keyword.
<> - Used for... ?
For Example, I see stuff like this all the time, but still not quite sure what the brackets means...
<TemplateContainer(GetType(TemplateItem))> _
Public Property MessageTemplate As ITemplate
VB.net uses parentheses for, among other things, arithmetic groupings and function parameters (both of which use parentheses in C#), as well as array subscripts and default-property parameters (both of which use brackets in C#), (indexers), etc. It also uses (Of ... ) to enclose a list of types (which would be enclosed in < ... > in C#, with no "Of" keyword.
Braces are used for array or set initialization expressions, and are also used when defining a generic type with multiple constraints (e.g. (Of Foo As {IEnumerable, IDisposable, Class})). Note that the latter usage is only permitted in constraints; it is alas not possible to e.g. Dim MyThing As {IEnumerable, IDisposable, Class}).
Braces are now also used for the New With {} construct:
Dim p = New Person With {.Name = "John Smith", .Age = 27}
Dim anon = New With {.Name = "Jack Smythe", .Age = 23}
Square brackets are used to enclose identifiers whose spelling would match that of a reserved word. For example, if a class defined a method called Not (perhaps the class was written in a language without a keyword Not), one could use such a method within VB by enclosing its name in square brackets (e.g. someVariable = [Not](5)). In the absence of the square brackets, the above expression would set someVariable to -6 (the result of applying the vb.net Not operator to the value 5).
Angle brackets, as noted elsewhere, are used for attributes. Note that in many cases, attributes are placed on the line above the thing they affect (so as to avoid pushing the affected variable past the right edge of the screen). In older versions of vb, such usage requires the use of a line-continuation mark (trailing underscore).
Angle brackets are also used for XML Literals and XML Axis Properties:
Dim xml = <simpleTag><anotherTag>text</anotherTag></simpleTag>
Console.WriteLine(xml.<anotherTag>.First.Value)
In this case it's used for the Attribute declaration. It can also be used in XML Literals as follows:
<TestMethod>
Public Sub ThisIsATest()
If 1 <> 0 Then
Dim foo = <root>
<child>this is some XML</child>
</root>
End If
End Sub
In VB.Net, <> is used to enclose Attributes.
VB.NET uses <> for attributes as well as to indicate "does not equal" (!=)
In your example it is just enclosing attributes. That same code in C# would be
[TemplateContainer(GetType(TemplateItem))]
public ITemplate MessageTemplate { get; set; }
This attribute is used in developing templated controls, which separate data from presentation. In other words, a templated control can retain the same functionality while changing it's appearance.
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...
Does anybody know what does the following construct mean:
Dim s1 as [String]
What do the square brackets mean? And why does the following statement with Integer fail while the one above, with String works?
Dim i1 as [Integer]
Thanks in advance.
THe square brackets is used so that the compiler interprets it as a type, even if it would be a keyword. Imagine for example if you had a class named As:
Dim a As [As]
This is usually only used in auto generated code, so that it works with any type that you throw at it.
The reason that you can't use [Integer] is that Integer is not a data type, it's a keyword. You would have to use the corresponding data type, i.e. [Int32].
Square brackets are used to create a variable that has the same name as a keyword in VB.NET. So they are more often used that way:
Dim [Integer] As Integer
Dim [String] As String
In addition to the other answers:
For the case of using variable names with names the same as types: you shouldn't have to use those in your own code. If you do, you are naming your variable names incredibly poorly, and need to work on using better variable names first!