34

I am using Window Application for my project. There is situation where i need to define string enum and using it in my project.

i.e.

Dim PersonalInfo As String = "Personal Info"
Dim Contanct As String = "Personal Contanct"

    Public Enum Test
        PersonalInfo
        Contanct
    End Enum

Now i want value of that variable PersonalInfo and Contract as "Personal Info" and "Personal Contanct".

How can i get this value using ENUM? or anyother way to do it.

Thanks in advance...

Brijesh Patel
  • 2,901
  • 15
  • 50
  • 73

7 Answers7

56

For non-integer values, Const in a Structure (or Class) can be used instead:

Structure Test
    Const PersonalInfo = "Personal Info"
    Const Contanct = "Personal Contanct"
End Structure

or in a Module for direct access without the Test. part:

Module Test
    Public Const PersonalInfo = "Personal Info"
    Public Const Contanct = "Personal Contanct"
End Module

In some cases, the variable name can be used as a value:

Enum Test
    Personal_Info
    Personal_Contanct
End Enum

Dim PersonalInfo As String = Test.Personal_Info.ToString.Replace("_"c, " "c)

' or in Visual Studio 2015 and newer:
Dim Contanct As String = NameOf(Test.Personal_Contanct).Replace("_"c, " "c)
Slai
  • 22,144
  • 5
  • 45
  • 53
  • 3
    The reason I prefer this over the class is because these enumerations are never meant to be instantiated. They are just enumerations of strings gathered together in a single place and then referred to elsewhere with the dot notation. Notice with this we don't declare any instance of this structure. It is a structure just for the purpose of containing the constants. You could do the same with a class. I've also seen people do readonly properties with a class. But these are string constants. So we use const. – Will Rickards May 29 '15 at 20:38
26

You could just create a new type

''' <completionlist cref="Test"/>
Class Test

    Private Key As String

    Public Shared ReadOnly Contact  As Test = New Test("Personal Contanct")
    Public Shared ReadOnly PersonalInfo As Test = New Test("Personal Info")

    Private Sub New(key as String)
        Me.Key = key
    End Sub

    Public Overrides Function ToString() As String
        Return Me.Key
    End Function
End Class

and when you use it, it kinda looks like an enum:

Sub Main

    DoSomething(Test.Contact)
    DoSomething(Test.PersonalInfo)

End Sub

Sub DoSomething(test As Test)
    Console.WriteLine(test.ToString())
End Sub

output:

Personal Contanct
Personal Info

sloth
  • 99,095
  • 21
  • 171
  • 219
  • 2
    The structure solution (by Slai) accomplishes the same thing in 4 lines of code. – Jon Harbour Aug 20 '14 at 19:13
  • 1
    @JonHarbour Erm... No. It doesn't. It just uses strings, so it's not as type safe as the strongly typed enum pattern, it can not be extended, and you can not add explicit conversions. Also, I don't see a point in using a structure over a module in this case. – sloth Aug 20 '14 at 20:47
  • If you want to compare objects like this in a `Select Case`, you should make `Key` Public and compare using `.Key`. – mbomb007 Mar 13 '17 at 17:13
11

How about using Tagging. Something like:

Public Enum MyEnum
<StringValue("Personal Contact")>Contact
<StringValue("My PersonalInfo")>PersonalInfo
End Enum

You would have to write the StringValue attribute as:

Public Class StringValueAttribute
    Inherits Attribute

    Public Property Value As String
    Public Sub New(ByVal val As String)
        Value = val
    End Sub

End Class

To get it out:

 Public Function GetEnumByStringValueAttribute(value As String, enumType As Type) As Object
    For Each val As [Enum] In [Enum].GetValues(enumType)
        Dim fi As FieldInfo = enumType.GetField(val.ToString())
        Dim attributes As StringValueAttribute() = DirectCast(fi.GetCustomAttributes(GetType(StringValueAttribute), False), StringValueAttribute())
        Dim attr As StringValueAttribute = attributes(0)
        If attr.Value = value Then
            Return val
        End If
    Next
    Throw New ArgumentException("The value '" & value & "' is not supported.")
End Function

Public Function GetEnumByStringValueAttribute(Of YourEnumType)(value As String) As YourEnumType
    Return CType(GetEnumByStringValueAttribute(value, GetType(YourEnumType)), YourEnumType)
End Function

And then a call to get the Enum (using string attribute):

Dim mEnum as MyEnum = GetEnumByStringValueAttribute(Of MyEnum)("Personal Contact")

To get the "Attribute" value out (removed handling 'Nothing' for clarity):

  Public Function GetEnumValue(Of YourEnumType)(p As YourEnumType) As String
        Return DirectCast(Attribute.GetCustomAttribute(ForValue(p), GetType(StringValueAttribute)), StringValueAttribute).Value
  End Function

  Private Function ForValue(Of YourEnumType)(p As YourEnumType) As MemberInfo
        Return GetType(YourEnumType).GetField([Enum].GetName(GetType(YourEnumType), p))
  End Function

And the call to get the string attribute (using Enum):

Dim strValue as String = GetEnumValue(Of MyEnum)(MyEnum.Contact)
Denis
  • 11,796
  • 16
  • 88
  • 150
  • how can I get the string constant? – Netorica Aug 22 '13 at 08:38
  • 3
    Way too convoluted just for a string enumeration. – Jon Harbour Aug 20 '14 at 18:52
  • 1
    It might look convoluted to some, but I think this is the best solution IMHO. In my case I really wanted it to work like Enum during comparisons. (EX: If myValue = Test.PersonalInfo...). – SnookerC Jan 23 '15 at 21:14
  • @Jon, it depends how you do it. I present the methods to handle attributes. If you have it as a helper class you can use the tagging anywhere and it becomes very useful especially if you have dealt with Enums in C# and loved that feature - sadly VB.NET Enums are missing that C# feature.. – Denis Feb 02 '15 at 14:28
5

How can i get this value using ENUM? or anyother way to do it.

There are three common ways of mapping enum values to strings:

  • Use a Dictionary(Of YourEnumType, String)
  • Decorate the enum values with attributes (e.g. DescriptionAttribute) and fetch them with reflection
  • Use a Switch statement

The first of these options is probably the simplest, in my view.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    thanks jon. Actually i am new at windows application. can you give me some more brief on first way (Dictionary..)? – Brijesh Patel Sep 07 '12 at 05:49
  • 6
    @BrijeshPatel: Stack Overflow isn't really a good way of learning from scratch. I suggest you read the `Dictionary` documentation, and ideally read a good VB book which should cover collections. – Jon Skeet Sep 07 '12 at 05:52
5

I know this is an old post put I found a nice solution that worth sharing:

''' <summary>
''' Gives acces to strings paths that are used often in the application
''' </summary>
Public NotInheritable Class Link        
    Public Const lrAutoSpeed As String          = "scVirtualMaster<.lrAutoSpeed>"
    Public Const eSimpleStatus As String        = "scMachineControl<.eSimpleStatus>"
    Public Const xLivebitHMI As String          = "scMachineControl<.xLivebitHMI>"      
    Public Const xChangeCycleActive As String   = "scMachineControl<.xChangeCycleActive>"

End Class

Usage:

'Can be anywhere in you applicaiton:
Link.xChangeCycleActive

This prevents unwanted extra coding, it's easy to maintain and I think this minimizes extra processor overhead.

Also visual studio shows the string attributes right after you type "Link" just like if it is a regular Enum

Rob Heijligers
  • 193
  • 1
  • 2
  • 9
2

If all you want to do is display the enums in a list or combo, you can use tagging such as

Private Enum MyEnum
    Select_an_option___
    __ACCOUNTS__
    Invoices0
    Review_Invoice
    __MEETINGS__
    Scheduled_Meetings0
    Open_Meeting
    Cancelled_Meetings0
    Current_Meetings0
End Enum

Then pull the MyEnum into a string and use Replace (or Regex) to replace the tags: "___" with "...", "__" with "**", "_" with " ", and remove trailing numbers. Then repack it up into an array and dump it into a combobox which will look like:

Select an option...
**ACCOUNTS**
Invoices
Review Invoice
**MEETINGS**
Scheduled Meetings
Open Meeting
Cancelled Meetings
Current Meetings

(You can use the numbers to, say, disable a text field for inputting an invoice number or meeting room. In the example, Review Invoice and Open Meeting might be expecting additional input so a text box might be enabled for those selections.)

When you parse the selected combo item, the enumeration will work as expected but you only really need to add a single line of code - the text replacement - to get the combo to look as you wish.

(The explanation is about 10 times as involved as the actual solution!)

SteveCinq
  • 1,920
  • 1
  • 17
  • 22
1

This technique from Microsoft - "How to: Determine the String Associated with an Enumeration Value (Visual Basic)" - will be useful in some situations (it didn't help with mine unfortunately though :( ). Microsoft's example:

VB:

Public Enum flavorEnum
    salty
    sweet
    sour
    bitter
End Enum

Private Sub TestMethod()
    MsgBox("The strings in the flavorEnum are:")
    Dim i As String
    For Each i In [Enum].GetNames(GetType(flavorEnum))
        MsgBox(i)
    Next
End Sub
Zeek2
  • 386
  • 4
  • 8