简体   繁体   English

我可以在VB.NET中给枚举一个属性(就像我可以用Java做的那样)吗?

[英]Can I give an enum an attribute in VB.NET (like I can do in Java)?

In Java I can do something like this: 在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;
    }
}

which allows me to do something like: 这让我可以这样做:

Country country1 = getCountryFromSomewhere();
Country country2 = Country.FRANCE;
System.out.print("country1 is in " + country1.getContinent());
System.out.print("country2 is in " + country2.getContinent());

Is it possible to do the same thing in VB.NET ie add the continent attribute to the country enum? 是否可以在VB.NET中执行相同的操作,即将continent属性添加到国家/地区枚举?

(Apologies for using C# throughout - I believe the concepts are more about .NET than the language you happen to use; hopefully you're better at reading C# than I am at writing VB.) (在整个过程中使用C#的道歉 - 我相信这些概念更多的是关于.NET而不是你碰巧使用的语言;希望你在阅读C#时比在编写VB时更好。)

Not directly - enums in .NET are just integer types with names for some of the values. 不直接 - .NET中的枚举只是整数类型,其中包含某些值的名称。

The closest you can come in .NET is to create a type with a fixed set of values. .NET中最接近的是创建一个具有固定值集的类型。 For example, in your case: 例如,在您的情况下:

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

(I assume the VB.NET would be very similar.) (我假设VB.NET非常相似。)

Note that this doesn't let you switch on the enum values. 请注意,这不允许您打开枚举值。

If you want polymorphism, you can create nested subclasses which can still call the private constructor, which prevents any other subclasses being created. 如果你想要多态,你可以创建嵌套的子类,它仍然可以调用私有构造函数,这可以防止创建任何其他子类。

One alternative to this is to use attributes on normal enums: 一种替代方法是在普通枚举上使用属性

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

public enum Country
{
    [Continent("Europe")] Ireland = 1,
    [Continent("Europe")] France = 2,
    ...
}

You'd then need to use reflection to get at the ContinentAttribute and retrieve the string. 然后,您需要使用反射来获取ContinentAttribute并检索字符串。

Note that here there isn't really a fixed set of values - you could write: 注意,这里确实没有一个固定的值-你可以写:

Country country = (Country) 15;

At that point you can't get the continent for it, and if you pass it to any methods which expect it to be a real country, you've got problems. 那时你无法获得它的大陆,如果你将它传递给任何期望它成为真实国家的方法,你就会遇到问题。 That isn't the case with the earlier solution, where you really are restricted to those few values (and null). 早期的解决方案并非如此,在这种解决方案中,您实际上只限于那些少数值(和null)。

Here is the code: 这是代码:

Imports System.ComponentModel 导入System.ComponentModel

Imports System.Reflection Imports 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

I used this solution instead: 我使用这个解决方案:

Declare enum: 声明枚举:

Private Enum Country
    IRELAND
    FRANCE
    THAILAND
End Enum

Declare and initialise Dictionary (aka a map): 声明并初始化Dictionary(又名地图):

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")

which allows me to get the continent like this: 这让我能够像这样进入大陆:

Dim franceContinent As String = countryContinentMap(Country.FRANCE)

Here is how I solved this in my application. 以下是我在应用程序中解决这个问题的方法。 Still looking for something even easier. 还在寻找更容易的东西。

What do you think about it? 你怎么看待这件事?

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

Create an extension method for your Enum 为您的Enum创建扩展方法

Usage example: 用法示例:

dim description = TableTag.Important.GetDescription()

Definition example: 定义示例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM