我能否在VB.NET中给枚举类型添加属性(就像在Java中一样)?

5

在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;
    }
}

这使我可以做类似于以下的操作:

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中是否可以做同样的事情,即将大洲属性添加到国家枚举中?


THAILAND("新加坡")... 作为一个新加坡人,我可以完全证明新加坡不是一个大陆,而泰国是一个完全不同的地方。 - BoltClock
更正了!我向新加坡(和泰国)的好人深表歉意... - CodeClimber
没关系,我其实觉得很有趣 :) - BoltClock
1
@BoltClock:在写答案的时候我也想过这个问题……但是我认为发布答案比纠正它更重要 :) - Jon Skeet
5个回答

8

抱歉全文内容使用C#编写 - 我相信这些概念更与.NET相关,而不是特定语言;希望您能够更好地阅读C#。

在.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,
    ...
}

您需要使用反射来获取ContinentAttribute并检索字符串。

请注意,这里没有真正的固定值 - 您可以编写:

Country country = (Country) 15;

在这种情况下,您无法获取该大陆,如果将其传递给任何期望它是一个真正的国家的方法,则会遇到问题。这与早期解决方案不同,在早期解决方案中,您确实受限于那些少数值(和null)。


1
有人怎么能在这么短的时间内写出这么多(值得阅读的)东西呢? - Tim Schmelter
5
他不仅仅是某个人。 - BoltClock
也许类似于预初始化的EnumMap? - Paŭlo Ebermann
嗨Jon,我已经为你的答案点赞了,因为我很感激你花时间写出来并且回答了我的问题(不,这是不可能的)。虽然我可能不会使用任何一种解决方案(而且我确实指定了我正在使用VB.NET),但我不会将其标记为被接受的答案。 - CodeClimber
@CodeClimber:这很公平。 (你真的不想让我写VB。它可能是可怕的代码 :) - Jon Skeet

5

以下是代码:

导入 System.ComponentModel

导入 System.Reflection

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

2

我使用了以下解决方案:

声明枚举:

Private Enum Country
    IRELAND
    FRANCE
    THAILAND
End Enum

声明并初始化字典(也称为映射):

Dim countryContinentMap As IDictionary(Of Country, String) = New Dictionary(Of Country, String)
countryContinentMap.add(Country.IRELAND, "Europe")
countryContinentMap.add(Country.FRANCE, "Europe")
countryContinentMap.add(Country.THAILAND, "Asia")

这让我可以像这样获取内容:

Dim franceContinent As String = countryContinentMap(Country.FRANCE)

枚举的优点在于您可以将所有内容放在一个地方,而不需要在许多位置进行更改。似乎VB.NET没有像C#那样提供这个功能。例如,我希望为我的枚举类型提供描述,以便简单地迭代它们。 - Matthis Kohli

0

这是我在我的应用程序中解决这个问题的方法。仍然在寻找更简单的方法。

你对此有何看法?

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

0

为您的枚举创建扩展方法

使用示例:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接