我可以在VB.NET中为枚举指定一个属性吗(就像在Java中一样)?

我可以在VB.NET中为枚举指定一个属性吗(就像在Java中一样)?,java,vb.net,enums,Java,Vb.net,Enums,在Java中,我可以执行以下操作: enum Country { IRELAND("Europe"), FRANCE("Europe"), NIGERIA("Africa"), THAILAND("Asia"); private String continent; Country(String continent) { this.continent = continent; } public String ge

在Java中,我可以执行以下操作:

enum Country {
    IRELAND("Europe"),
    FRANCE("Europe"),
    NIGERIA("Africa"),
    THAILAND("Asia");

    private String continent;

    Country(String continent) {
        this.continent = continent;
    }

    public String getContinent() {
        return continent;
    }
}
Dim franceContinent As String = countryContinentMap(Country.FRANCE)
这让我可以做一些类似的事情:

Country country1 = getCountryFromSomewhere();
Country country2 = Country.FRANCE;
System.out.print("country1 is in " + country1.getContinent());
System.out.print("country2 is in " + country2.getContinent());
是否可以在VB.NET中执行相同的操作,即将大陆属性添加到国家枚举中?

(抱歉在整个过程中使用C#,我相信这些概念更多地是关于.NET的,而不是您碰巧使用的语言;希望您在阅读C#方面比我在编写VB方面做得更好。)

不是直接的-NET中的枚举只是整数类型,其中一些值具有名称

在.NET中,最接近的方法是创建一个具有固定值集的类型。例如,在您的情况下:

public sealed class Country
{
    public static readonly Country Ireland = new Country("Europe");
    public static readonly Country France = new Country("Europe");
    public static readonly Country Nigeria = new Country("Africa");
    public static readonly Country Thailand = new Country("Asia");

    private readonly string continent;

    public string Continent { get { return continent; } }

    private Country(string continent)
    {
        this.continent = continent;
    }
}
(我假设VB.NET与之非常相似。)

请注意,这不允许打开枚举值

如果需要多态性,可以创建嵌套的子类,该子类仍然可以调用私有构造函数,从而防止创建任何其他子类

一种替代方法是在普通枚举上使用属性:

[AttributeUsageAttribute(AttributeTargets.Field)]
public class ContinentAttribute : Attribute
{
    // etc
}

public enum Country
{
    [Continent("Europe")] Ireland = 1,
    [Continent("Europe")] France = 2,
    ...
}
然后,您需要使用反射来获取
属性
,并检索字符串

请注意,这里并没有一组固定的值-您可以编写:

Country country = (Country) 15;

在这一点上,你无法得到欧洲大陆,如果你把它传递给任何期望它成为一个真正的国家的方法,你就会遇到问题。早期的解决方案并非如此,在早期的解决方案中,您实际上被限制为这几个值(和null)。

我使用了这个解决方案:

声明枚举:

Private Enum Country
    IRELAND
    FRANCE
    THAILAND
End Enum
声明并初始化字典(也称为映射):

这让我可以像这样了解整个大陆:

enum Country {
    IRELAND("Europe"),
    FRANCE("Europe"),
    NIGERIA("Africa"),
    THAILAND("Asia");

    private String continent;

    Country(String continent) {
        this.continent = continent;
    }

    public String getContinent() {
        return continent;
    }
}
Dim franceContinent As String = countryContinentMap(Country.FRANCE)
代码如下:

导入System.ComponentModel

输入系统。反射

Public Enum enumOrderStatus
    <Description("None")>
    None
    <Description("Sent")>
    Sent
    <Description("Accepted")>
    Accepted
    <Description("Cancelled")>
    Cancelled
    <Description("Declined")>
    Declined
End Enum


Public Function GetEnumDescription(ByVal EnumConstant As [Enum]) As String
    Dim fi As FieldInfo = EnumConstant.GetType().GetField(EnumConstant.ToString())
    Dim aattr() As DescriptionAttribute = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
    If aattr.Length > 0 Then
        Return aattr(0).Description
    Else
        Return EnumConstant.ToString()
    End If
End Function
公共枚举enumOrderStatus
没有一个
发送
认可的
取消
拒绝
结束枚举
公共函数GetEnumDescription(ByVal EnumConstant作为[Enum])作为字符串
Dim fi As FieldInfo=EnumConstant.GetType().GetField(EnumConstant.ToString())
Dim aattr()作为DescriptionAttribute=DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute),False),DescriptionAttribute())
如果aattr.长度>0,则
返回aattr(0)。说明
其他的
返回EnumConstant.ToString()
如果结束
端函数

以下是我在应用程序中解决此问题的方法。仍然在寻找更简单的东西

你觉得怎么样

Public Sub Init()
    Dim values() As Integer = CType([Enum].GetValues(GetType(MyEnum)), Integer())
    For i As Integer = 0 To values.Count - 1
        Me.contextMenuInGUI.Items.Add(Me.GetEnumDescription(i))
    Next
End Sub

Private Function GetEnumDescription(ByVal i As Integer) As String
    Select Case i
        Case MyEnum.Comment
            Return "Description for Comment"

        Case MyEnum.SomeEnumValueInCamelCase
            Return "Value without camel case (€)(%)(@)"
    End Select
    Return "Add a case in Class:GetEnumDescription"
End Function

为枚举创建扩展方法

用法示例:

dim description = TableTag.Important.GetDescription()
定义示例:

Imports System.ComponentModel
Imports System.Reflection
Imports System.Runtime.CompilerServices

Namespace Foo

  Public Enum TableTag

    <Description("Identifies tables that should be availible for writing as table or view to the model database")>
    Important

    <Description("Example for a table group that helps to select disctinct tables")>
    CustomGroup

  End Enum

  Public Module TableTagExtensions

    <Extension>
    Public Function GetDescription(enumValue As TableTag) As String

      Dim fieldInfo As FieldInfo = enumValue.GetType().GetField(enumValue.ToString())
      Dim attributes = DirectCast(fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

      If attributes.Length > 0 Then
        Return attributes(0).Description
      Else
        Return enumValue.ToString()
      End If

    End Function

  End Module

End Namespace
导入System.ComponentModel
输入系统。反射
导入System.Runtime.CompilerServices
名称空间Foo
公共枚举表标签
重要的
客户群
结束枚举
公共模块表扩展
公共函数GetDescription(enumValue作为TableTag)作为字符串
Dim fieldInfo As fieldInfo=enumValue.GetType().GetField(enumValue.ToString())
Dim attributes=DirectCast(fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute),False),DescriptionAttribute())
如果attributes.Length>0,则
返回属性(0)。说明
其他的
返回enumValue.ToString()
如果结束
端函数
端模块
结束命名空间

泰国(“新加坡”)
。。。作为一个新加坡人,我可以完全保证新加坡不是一个大陆,泰国是一个完全不同的地方。更正!我向新加坡(和泰国)的善良人民致以最深切的歉意……没关系,我真的觉得这很有趣:)@BoltClock:我在写我的答案时对此感到疑惑。。。但我认为发布答案比更正答案更重要:)一个人怎么能在这么短的时间内写出这么多(值得一读)的东西?@Tim Schmelter:他不仅仅是一个人。也许是类似于预先初始化的地图的东西?嗨,Jon,我对你的答案投了更高的票,因为我感谢你花了这么多时间写出来,你回答了我的问题(不,这是不可能的)。我不会将其标记为已接受的答案,因为我可能不会使用任何一种解决方案(并且我确实指定了我使用的是VB.NET)。@codelimber:这很公平。(但你真的不想让我写VB。这可能会是可怕的代码:)枚举的优点是你的东西放在一个地方,不需要在很多地方更改。看起来VB.NET不像C#那样提供这些。我很想为我的枚举做一个描述,比如简单地迭代它们。