C#:有没有办法对枚举进行分类?

发布于 2024-08-18 07:08:45 字数 227 浏览 1 评论 0原文

给定以下枚举:

    public enum Position
    {
        Quarterback,
        Runningback,
        DefensiveEnd,
        Linebacker
    };

是否可以对命名常量进行分类,以便我可以将“四分卫”和“跑卫”标记为进攻位置,将“防守端”和“线卫”标记为防守位置?

Given the following enum:

    public enum Position
    {
        Quarterback,
        Runningback,
        DefensiveEnd,
        Linebacker
    };

Is it possible to classify the named constants, such that I could mark 'Quarterback' and 'Runningback' as offensive positions and 'DefensiveEnd' and 'Linebacker' as defensive positions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

野生奥特曼 2024-08-25 07:08:45

您可以使用属性:

public enum Position
{
    [OffensivePosition]
    Quarterback,
    [OffensivePosition]
    Runningback,
    [DefensivePosition]
    DefensiveEnd,
    [DefensivePosition]
    Linebacker
};

然后在适当的 FieldInfo 上检查 IsDefined。语法不是很漂亮,但是您可以添加一些扩展方法以使事情更易于管理:

public static bool IsOffensivePosition(PositionType pt)
{
    return typeof(PositionType).GetField(Enum.GetName(typeof(PositionType), pt)).
        IsDefined(typeof(OffensivePositionAttribute), false);
}

You can use attributes:

public enum Position
{
    [OffensivePosition]
    Quarterback,
    [OffensivePosition]
    Runningback,
    [DefensivePosition]
    DefensiveEnd,
    [DefensivePosition]
    Linebacker
};

And then check for IsDefined on an appropriate FieldInfo. Syntax is not very pretty, but you can throw in a couple of extension methods to make things more manageble:

public static bool IsOffensivePosition(PositionType pt)
{
    return typeof(PositionType).GetField(Enum.GetName(typeof(PositionType), pt)).
        IsDefined(typeof(OffensivePositionAttribute), false);
}
挽梦忆笙歌 2024-08-25 07:08:45

为什么不接吻:

class PlayerPosition {
    public enum Position {
        Quarterback,
        Runningback,
        DefensiveEnd,
        Linebacker
    }

    public enum Type {
        Offense,
        Defense
    }


    public static Type GetTypeForPosition(Position position) {
        switch (position) {
            case Quarterback:
            case Runningback:
                return Type.Offense;
            case DefensiveEnd:
            case Linebacker:
                return Type.Defense;

        }
    }
}

Why not KISS:

class PlayerPosition {
    public enum Position {
        Quarterback,
        Runningback,
        DefensiveEnd,
        Linebacker
    }

    public enum Type {
        Offense,
        Defense
    }


    public static Type GetTypeForPosition(Position position) {
        switch (position) {
            case Quarterback:
            case Runningback:
                return Type.Offense;
            case DefensiveEnd:
            case Linebacker:
                return Type.Defense;

        }
    }
}
树深时见影 2024-08-25 07:08:45

您可以使用属性,例如 CategoryAttribute

public enum Position
{
    [Category("Offensive")]
    Quarterback,
    [Category("Offensive")]
    Runningback,
    [Category("Defensive")]
    DefensiveEnd,
    [Category("Defensive")]
    Linebacker
};

You could use an attribute, like CategoryAttribute :

public enum Position
{
    [Category("Offensive")]
    Quarterback,
    [Category("Offensive")]
    Runningback,
    [Category("Defensive")]
    DefensiveEnd,
    [Category("Defensive")]
    Linebacker
};
北城半夏 2024-08-25 07:08:45
public enum PositionType
{
    Offensive,
    Defensive,
}

public class PositionTypeAttribute : Attribute
{
    public PositionTypeAttribute(PositionType positionType)
    {
        PositionType = positionType;
    }
    public PositionType PositionType { get; private set; }
}

public enum Position
{
    [PositionType(PositionType.Offensive)]
    Quarterback,
    [PositionType(PositionType.Offensive)]
    Runningback,
    [PositionType(PositionType.Defensive)]
    DefensiveEnd,
    [PositionType(PositionType.Defensive)]
    Linebacker
};

public static class PositionHelper
{
    public static PositionType GetPositionType(this Position position)
    {
        var positionTypeAttr = (PositionTypeAttribute)typeof(Position).GetField(Enum.GetName(typeof(Position), position))
            .GetCustomAttributes(typeof(PositionTypeAttribute), false)[0];
        return positionTypeAttr.PositionType;

    }
}


Position position1 = Position.Runningback;
Console.WriteLine(position1.GetPositionType()); //print: Offensive

Position position2 = Position.Linebacker;
Console.WriteLine(position2.GetPositionType()); //print: Defensive
public enum PositionType
{
    Offensive,
    Defensive,
}

public class PositionTypeAttribute : Attribute
{
    public PositionTypeAttribute(PositionType positionType)
    {
        PositionType = positionType;
    }
    public PositionType PositionType { get; private set; }
}

public enum Position
{
    [PositionType(PositionType.Offensive)]
    Quarterback,
    [PositionType(PositionType.Offensive)]
    Runningback,
    [PositionType(PositionType.Defensive)]
    DefensiveEnd,
    [PositionType(PositionType.Defensive)]
    Linebacker
};

public static class PositionHelper
{
    public static PositionType GetPositionType(this Position position)
    {
        var positionTypeAttr = (PositionTypeAttribute)typeof(Position).GetField(Enum.GetName(typeof(Position), position))
            .GetCustomAttributes(typeof(PositionTypeAttribute), false)[0];
        return positionTypeAttr.PositionType;

    }
}


Position position1 = Position.Runningback;
Console.WriteLine(position1.GetPositionType()); //print: Offensive

Position position2 = Position.Linebacker;
Console.WriteLine(position2.GetPositionType()); //print: Defensive
夏花。依旧 2024-08-25 07:08:45

您可以使用标志

[Flags]
public enum Position
    {
        Quarterback = 1,
        Runningback = 2,
        DefensiveEnd = 4,
        Linebacker = 8,

        OffensivePosition = Quarterback | Runningback,
        DefensivePosition =  Linebacker | DefensiveEnd, 

    };

    //strictly for example purposes
    public bool isOffensive(Position pos)
    {
        return !((pos & OffensivePosition) == pos);
    }

You could use Flags

[Flags]
public enum Position
    {
        Quarterback = 1,
        Runningback = 2,
        DefensiveEnd = 4,
        Linebacker = 8,

        OffensivePosition = Quarterback | Runningback,
        DefensivePosition =  Linebacker | DefensiveEnd, 

    };

    //strictly for example purposes
    public bool isOffensive(Position pos)
    {
        return !((pos & OffensivePosition) == pos);
    }
为人所爱 2024-08-25 07:08:45

也许您可以尝试使用 typesefe 枚举模式

class Position
{
    public bool Offensive { get; private set; }
    public bool Defensive { get; private set; }

    private Position()
    {
        Offensive = false;
        Defensive = false;
    }

    public static readonly Position Quarterback = new Position() { Offensive = true };
    public static readonly Position Runningback = new Position() { Offensive = true };
    public static readonly Position DefensiveEnd = new Position() { Defensive = true };
    public static readonly Position Linebacker = new Position() { Defensive = true };
}

Maybe you can try to use typesefe enum pattern

class Position
{
    public bool Offensive { get; private set; }
    public bool Defensive { get; private set; }

    private Position()
    {
        Offensive = false;
        Defensive = false;
    }

    public static readonly Position Quarterback = new Position() { Offensive = true };
    public static readonly Position Runningback = new Position() { Offensive = true };
    public static readonly Position DefensiveEnd = new Position() { Defensive = true };
    public static readonly Position Linebacker = new Position() { Defensive = true };
}
情深如许 2024-08-25 07:08:45

您可以使用某种形式的标志位。但这可能会导致混乱。更好的方法可能是仅使用所需的详细信息创建自定义类,然后使用字典来查找每个职位类型;

public class PlayerPosition {
    public PlayerPosition (string positionName, bool isDefensive ) {
        this.Name = positionName;
        this.IsDefensive = isDefensive ;
    }
    public string Name { get; private set; }
    public bool IsDefensive { get; private set; }
}

...作为枚举...

[Flags]
public enum Positions {
    Quarterback = 0x21, 
    Runningback = 0x22, 
    DefensiveEnd = 0x14, 
    Linebacker = 0x18, 

    Defensive = 0x10,
    Offsensive = 0x20
}

You could use some form of flag bits. But that could lead to a mess. A better way may be to just create custom classes with the details you want and then use a Dictionary to lookup each position type;

public class PlayerPosition {
    public PlayerPosition (string positionName, bool isDefensive ) {
        this.Name = positionName;
        this.IsDefensive = isDefensive ;
    }
    public string Name { get; private set; }
    public bool IsDefensive { get; private set; }
}

... as enum ...

[Flags]
public enum Positions {
    Quarterback = 0x21, 
    Runningback = 0x22, 
    DefensiveEnd = 0x14, 
    Linebacker = 0x18, 

    Defensive = 0x10,
    Offsensive = 0x20
}
余厌 2024-08-25 07:08:45

一种未充分利用(但完全有效)的技术是使用定义一组常量的类。作为一个类,您可以添加其他属性来描述枚举值的其他方面。奇怪的是,这是大多数枚举在 Java 中实现的方式(Java 没有专门的关键字)。

如果您走这条路,通常最好将类密封并定义私有构造函数,以便只有类本身可以定义实例。这是一个例子:

public static class Position 
{
    private PlayerPosition (string name, bool isDefensive ) {
        this.Name = name
        this.IsDefensive = isDefensive ;
    }
    // any properties you may need...
    public string Name { get; private set; }
    public bool IsDefensive { get; private set; }
    public bool IsOffensive { get { return !IsDefensive; } }

    // static instances that act like an enum
    public static readonly Quarterback = new PlayerPosition( "Quarterback", false );
    public static readonly Runningback = new PlayerPosition( "Runningback", false );
    public static readonly Linebacker = new PlayerPosition( "Linebacker", true );
    // etc...
}

使用这样的枚举会产生比属性更优雅、更简单的语法:

if( PlayerPosition.Quarterback.IsDefensive )
{
    // ...
}

An underutilized (but perfectly valid) technique is to use a class which defines a set of constants. As a class, you can add additional properties that can describe other aspects of the enumerated value. Curiously, this is the way most enums are implemented in Java (which doesn't have a special keyword for them).

If you go this route, it's generally a good idea to make the class sealed and define a private constructor, so that only the class itself can define instances. Here's an example:

public static class Position 
{
    private PlayerPosition (string name, bool isDefensive ) {
        this.Name = name
        this.IsDefensive = isDefensive ;
    }
    // any properties you may need...
    public string Name { get; private set; }
    public bool IsDefensive { get; private set; }
    public bool IsOffensive { get { return !IsDefensive; } }

    // static instances that act like an enum
    public static readonly Quarterback = new PlayerPosition( "Quarterback", false );
    public static readonly Runningback = new PlayerPosition( "Runningback", false );
    public static readonly Linebacker = new PlayerPosition( "Linebacker", true );
    // etc...
}

Using such an enum results in more elegant and simpler syntax than attributes:

if( PlayerPosition.Quarterback.IsDefensive )
{
    // ...
}
潜移默化 2024-08-25 07:08:45

您可以在类中声明枚举:

public class Position
{
    public enum Offensive { Quarterback = 1, RunningBack }
    public enum Defensive { DefensiveEnd = 10, LineBacker }
}

请注意,防御值从 10 开始,以便值不会重叠。您没有说明为什么要这样做,因此这可能无法满足您的需求。

You can declare the enums in a class:

public class Position
{
    public enum Offensive { Quarterback = 1, RunningBack }
    public enum Defensive { DefensiveEnd = 10, LineBacker }
}

Note that the Defensive values start at 10 so that values don't overlap. You don't state why you want to do this, so this might not meet your needs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文