VB can't get the right function to work with strings - vb.net

Basically, I'm trying to do some string manipulation to edit directories.
I found some code to try and edit the directories, but when I use it it doesn't recognise 'right' as being a function and only recognises it as a right property, thus producing an error.
I was wondering if there's something I haven't imported or if perhaps 'right' is an obsolete function that was used in VB6 but replaced with something.
The code I have is as follows:
Dim Foo As String
Dim Bar As String
Bar = 'some form of directory input i.e. my.computer.currentdirectory
Foo = right(Bar, (Len(Bar) - InStrRev(Bar, "/")))
MsgBox(Foo)
Ideally I need either a better method of manipulating directories or a way to get the 'right' functionality working.

but when I use it it doesn't recognise 'right' as being a function and only recognises it as a right property, thus producing an error.
If you have a "right" property, you can fully qualify the function:
Foo = Microsoft.VisualBasic.Right(Bar, (Len(Bar) - InStrRev(Bar, "/")))
For details, see the docs for the Right Function.
Note that, for directory parsing, you can handle this much more cleanly via the System.IO namespace. In particular, you can construct a DirectoryInfo and get the parent folder via the Parent property.
You can also use Path.GetDirectoryName to work with strings. In your case, if you had Bar set to "C:\Some\Path\To\A\File.txt" and you call Path.GetDirectoryName(Bar), it will return "C:\Some\Path\To\A". If you call it on that, you'll get ""C:\Some\Path\To", etc.

Look up System.IO.Path - has lots of useful tools for this stuff. You'll want GetDirectoryName and GetFileName especially. They work on directories as well as filenames.
Bar = "C:\Dir1\Dir2\Dir3"
Foo = IO.Path.GetFileName(Bar) 'now = Dir3
Foo = IO.Path.GetDirectoryName(Bar) 'now = C:\Dir1\Dir2
http://msdn.microsoft.com/en-us/library/system.io.path.getfilename
http://msdn.microsoft.com/en-us/library/system.io.path.getdirectoryname

Related

VB.net String Reverse Property different based on Env

I am debugging an application that runs on a server and users will access the application on another server. The application uses encryption and as part of the key, I am using the String.Reverse property.
Dim Mystring As String = "123abc"
Dim reverse = String.Format("{0},{1}", Mystring.Reverse)
The string reverse is different when I run it from one machine (RDP/Citrix Environment ASP.NET 4.6.1). The value is:
System.Linq.Enumerable+<ReverseIterator>d__a2`1[System.Char]
The same string, but ran from another machine (RPD non-Citrix Environment ASP.NET 4.5.2). The value of reverse is:
System.Linq.Enumerable+<ReverseIterator>d__73`1[System.Char]
Why are the values different in the different environments?
Look at this line first:
Dim reverse = String.Format("{0},{1}", Mystring.Reverse)
Specifically, this expression:
Mystring.Reverse
Reverse is a function, not a property, but it's missing the parentheses (). The trick here is the String.Format() method accepts the base Object type as an argument, and compiler is able to treat the MyString.Reverse expression as a delegate type that is convertible to object. The values you see in your output are the result of calling .ToString() on that function delegate. It's the type name for the function, rather than anything to do with the value of your MyString object. Since that type is dynamically and randomly generated at runtime, you'll see different values not only on different platforms, but different runs on the same computer.
In the VB6 era, it was normal to call methods without the parentheses. In the .Net world, always use parentheses when you call a method.
What you want is this:
Dim reverse As String = String.Format("{0},{1}", Mystring.Reverse())
Even here, you're missing the second argument to match the format string. I doubt you'll get the result you expect.
Finally, reversing a string as the key seems very wrong when it comes to encryption. You are using a real cyrptogrpahic algorithm from the System.Security.Cryptography library, right? Right!?
You are not outputting the value of the reversed String but the name of the type used to perform the reversal. That type is dynamically created and randomly named. The "d" in those two names means "dynamic" and the "a2" and "73" parts are random.
Basically, what you perceive to be an issue is not an issue. The problem is that you're not actually creating a String from the reversed output. You say "String.Reverse property but that is NOT a property. It is a method and it is not a member of the String class but rather an extension method on the IEnumerable(Of T) interface. You are treating your String as an enumerable list of Char values and reversing that. If you want a String from that then you need to create one, i.e.
MyReversedString = New String(Mystring.Reverse().ToArray())
That will push the contents of your iterator into an array and then create a new String object from that array.

How can I get the display name from my enum

I have researched and it seems that most is bouncing around the problem I have.
#Code
#Imports System.ComponentModel
Dim values = New SelectList([Enum].GetNames(GetType(myEnum)).GetAttribute<DisplayAttribute>()
End Code
The last pararenthesis has a blue line under it and when hover tells me an expression is expected. I want to capture the display name from my enum and have tried many things found on the google search without success. Why am I getting the expression expected error?
Attempted to incorporate and now getting at end parenthesis
Dim type = typeof(MyEnum) ls is expected.
You might want to have a look at this awesome NuGet package called UnconstrainedMelody from Jon Skeet.
https://www.nuget.org/packages/UnconstrainedMelody/
Helpful static methods (or extension methods) for enums and delegates, with constraints which can't be expressed in regular C#.
Have a look at the functions UnconstrainedMelody.Enums.GetNames() and UnconstrainedMelody.Enums.GetValues()

Using String variable as an expression

Passing commands as variables. I am creating a POP3 client and was crunching through some code when I though of something interesting.
Is it possible to pass strings of vb code to an object so that the object will execute it. I am relatively familiar with vb.net's source code being converted to Intermediate language and then being thrown into a JIT virtual machine, but I was hoping there was a simple way to implement this idea.
I want to be able to use strings
Dim Command as string
Command = "If a + b > 0 then c = a + b" '<----syntactical sugar!
System.Compiler.Something.execute(command)
If anyone has any direction, or any correction to any of the above. I appreciate your time.
Rah!
As a start you may want to check out the open source FileHelpers project.
The Runtime.ClassBuilder class in that project creates a .Net class from text, which can then be used as a normal class.

Enforce Type Alias in VB.NET

How might one go about aliasing a type in VB.NET or C# such that when the alias is used as an argument type in a function, accidentally using the not aliased type is an error?
i.e.
Imports AccessSpecifier = System.String
Module Accessors
Delegate Function IoOper(ByRef strm As System.IO.Stream) As Action
Public Function accessMethod(ByRef spec As AccessSpecifier) As IoOper
' implementation
' ...
End Function
End Module
Module Main
Public Sub Main()
Dim spec As AccessSpecifier = New AccessSpecifier(CType("READ_WRITE", Char()))
Dim val = Accessors.accessMethod(spec)
System.Console.WriteLine(val.GetType())
Dim shouldFail = Accessors.accessMethod("FAIL_ME")
System.Console.WriteLine(shouldFail.GetType())
End Sub
End Module
Or perhaps is there a better way to go about this?
Overall, I'm wanting the IDE to force me to know what I'm doing if I'm throwing Ints around to mean Flags, or States and Strings around to mean Names, Propertys and Records.
Help?
I've never liked Type aliasing in .NET. It makes for imprecise code and it is not immediately clear what is happening. As in your example, when an individual went looking for the AccessSpecifier.vb file (or class) they would not find it.
Also, Aliasing only works within YOUR project and only within a single code file. So you would have to define that alias in all the various code files where it was to be used.
A better (as in easier to read, easier to maintain, and more clear of intent) option is to create a class and overload the type conversion operators for automatic conversion to/from String. In this manner you retain your ability to use your new class as if it were a String, but you gain your strict type checking.

How to access the object itself in With ... End With

Some code to illustrate my question:
With Test.AnObject
.Something = 1337
.AnotherThing = "Hello"
''// why can't I do this to pass the object itself:
Test2.Subroutine(.)
''// ... and is there an equivalent, other than repeating the object in With?
End With
There is no way to refer to the object referenced in the With statement, other than repeating the name of the object itself.
EDIT
If you really want to, you could modify your an object to return a reference to itself
Public Function Self() as TypeOfAnObject
Return Me
End Get
Then you could use the following code
With Test.AnObject
Test2.Subroutine(.Self())
End With
Finally, if you cannot modify the code for an object, you could (but not necessarily should) accomplish the same thing via an extension method. One generic solution is:
' Define in a Module
<Extension()>
Public Function Self(Of T)(target As T) As T
Return target
End Function
called like so:
Test2.Subroutine(.Self())
or
With 1
a = .Self() + 2 ' a now equals 3
End With
I suspect you'll have to repeat yourself. If the expression (to get the object) is expensive, then perhaps drop it into a variable first, and either use that variable in the With, or drop the With completely:
tmp = Test.AnObject;
tmp.Something = 1337;
...
Test2.Subroutine(tmp);
As others have said, you're going to have to write
Test2.Subroutine(Test.AnObject)
This is a good example of why it's worth being a little careful with the With construct in VB.Net. My view is that to make it worth using at all, you really need to be setting more than one or two properties, and/or calling more than one or two methods on the object in the With statement.
When there are lots, and you're not interspersing the .SomeProperty = , or .DoSomething, with other things, it's a terrific aid to readability.
Conversely, a few dots sprinkled amongst a load of other stuff is actually a lot harder to read than not using With at all.
In this case, . characters on their own could easily get lost visually, although of course, it would be syntactically consistent.
I guess they just chose not to implement it. VB isn't really the sort of language where they want to encourage single character language elements, and as a heavy user of VB.Net, I broadly agree with that.
Bottom line: if you're using a With clause with many contained elements, having to refer to the object itself isn't that big a deal. If you're using it with just one or two, maybe better not to use a With clause in the first place.
I'm not sure this is an "answer", per se, but it does illustrate another reason to want a short-hand reference to the parent in a With.
Here's a code sample using a "bare With" (that's what I call it, anyway):
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = .lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
But you actually can't code that because in the term .Start = .lblLinkLabel.Text.IndexOf("link") the compiler expects anything starting with . to be a member of LinkLabel.Link, which .lblLinkLabel isn't.
What would be good, I think, is to be able to write something like:
With New frmMySubForm
.lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = Me.lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
...
End With
where Me in this scope is taken to be New frmMySubForm.
Yes, I realize that I'm being picky and I could easily assign a variable, etc. But the example form is something I use a lot simply out of preference.