C# 枚举加法

发布于 2024-08-20 23:55:35 字数 233 浏览 4 评论 0原文

我有以下枚举:

public enum LegalShipTypes : byte
{
    Frigate = 1,
    Cruiser = 2,
    Destroyer = 3,
    Submarine = 4,
    AircraftCarrier = 5
}

有没有办法以任何方式获取枚举的总价值?例如,这将导致 (1 + 2 + 3 + 4 + 5) = 15。

I have the following enum:

public enum LegalShipTypes : byte
{
    Frigate = 1,
    Cruiser = 2,
    Destroyer = 3,
    Submarine = 4,
    AircraftCarrier = 5
}

Is there is a way to get the total value of enum in any way? For instance, this would result in (1 + 2 + 3 + 4 + 5) = 15.

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

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

发布评论

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

评论(7

娇女薄笑 2024-08-27 23:55:35

如果您可以编辑枚举,并且在许多地方需要它们的总和,则可以将其放在枚举本身中:

public enum LegalShipTypes : byte {
  Frigate = 1,
  Cruiser = 2,
  Destroyer = 3,
  Submarine = 4,
  AircraftCarrier = 5,
  All = Frigate + Cruiser + Destroyer + Submarine + AircraftCarrier
} 

但这在标志枚举中更有意义:

[Flags]
public enum LegalShipTypes : byte {
  Frigate = 1,
  Cruiser = 2,
  Destroyer = 4,
  Submarine = 8,
  AircraftCarrier = 16,
  All = Frigate | Cruiser | Destroyer | Submarine | AircraftCarrier
} 

或者您可以只使用它:

Enum.GetValues(typeof(LegalShipTypes)).Cast<byte>().Sum(x=>x)

它返回一个小数.

但这是一种更通用的方法(无论枚举的基础类型如何):

public decimal Sum(Type enumType) {
  return Enum
    .GetValues(enumType)
    .Cast<object>()
    .Sum(x => (decimal)Convert.ChangeType(x, typeof(decimal)));
}

If you can edit the enum, and you need their sum in many places, you can put it in the enum itself:

public enum LegalShipTypes : byte {
  Frigate = 1,
  Cruiser = 2,
  Destroyer = 3,
  Submarine = 4,
  AircraftCarrier = 5,
  All = Frigate + Cruiser + Destroyer + Submarine + AircraftCarrier
} 

This makes more sense in flags enums though:

[Flags]
public enum LegalShipTypes : byte {
  Frigate = 1,
  Cruiser = 2,
  Destroyer = 4,
  Submarine = 8,
  AircraftCarrier = 16,
  All = Frigate | Cruiser | Destroyer | Submarine | AircraftCarrier
} 

Or you can just use this:

Enum.GetValues(typeof(LegalShipTypes)).Cast<byte>().Sum(x=>x)

Which returns a decimal.

But this is a more general way to do it (works regardless of the underlying type of the enum):

public decimal Sum(Type enumType) {
  return Enum
    .GetValues(enumType)
    .Cast<object>()
    .Sum(x => (decimal)Convert.ChangeType(x, typeof(decimal)));
}
像你 2024-08-27 23:55:35

我不想将其作为答案输入,因为它不会直接回答您的问题,但根据您对我对您问题的评论的评论,它值得一些解释。

枚举是非常简单的类型安全的状态表示。如果您只是使用常量,那么您可能会将错误的常量分配给一个值。这可以防止您将错误类型的常量分配给字段。例如,如果您有需要 DayOfWeek 的内容,则无法分配 FileAccess 值,即使它们都是同一基础类型的常量。

DayOfWeek day = FileAccess.Write; // doesn't work

如果您需要这种类型安全并且您不需要枚举表现出任何其他类型的行为,那么请使用枚举。如果您担心让枚举也执行其他操作(例如枚举、数学运算等),那么您应该考虑使用类。请参阅下面我的示例。

public class LegalShipTypes
{
    private readonly byte _numericValue;
    private readonly string _text;

    private LegalShipTypes(byte numericValue, string text)
    {
        _numericValue = numericValue;
        _text = text;
    }

    public byte Value { get { return _numericValue; } }
    public string Text { get { return _text; } }

    public static IEnumerable<LegalShipTypes> All
    {
        get
        {
            return new[] { Frigate, Cruiser, Destroyer, Submarine, AircraftCarrier };
        }
    }

    public static readonly LegalShipTypes Frigate = new LegalShipTypes(1, "Frigate");
    public static readonly LegalShipTypes Cruiser = new LegalShipTypes(2, "Cruiser");
    public static readonly LegalShipTypes Destroyer = new LegalShipTypes(3, "Destroyer");
    public static readonly LegalShipTypes Submarine = new LegalShipTypes(4, "Submarine");
    public static readonly LegalShipTypes AircraftCarrier = new LegalShipTypes(5, "Aircraft Carrier");
}

现在您可以以类型安全的方式使用它,如下所示:

public class Fleet
{
    private readonly List<LegalShipTypes> _ships;

    public Fleet()
    {
        _ships = new List<LegalShipTypes>();
    }

    public LegalShipTypes Flagship { get; set; }
    public ICollection<LegalShipTypes> Ships { get { return _ships; } }
}

....

var fleet = new Fleet();
fleet.FlagShip = LegalShipTypes.AircraftCarrier;
var iDoNotKnowWhyYouWouldNeedThisBut = LegalShipTypes.All.Sum(ship => ship.Value);
Console.WriteLine("The flagship is a(n) \"{0}\".", fleet.FlagShip.Text);
if (fleet.FlagShip == LegalShipTypes.AircraftCarrier) // this will work because it's a reference comparison
    Console.WriteLine("This should be true");

如您所见,您仍然具有类型安全性,但灵活性更高。它是更多的代码,但您不会发现自己正在克服枚举的限制。重申一下,枚举的目的很简单。这应该很简单。如果您的需求很简单,请不要犹豫使用它。如果您的需求更复杂,那么使用良好的老式面向对象编程来解决您的问题并没有什么可耻的。

编辑

根据您最后的评论回复,字节值代表钉子的数量,我强烈建议您不要使用枚举来解决您的问题。你会(讽刺地)试图将圆钉放入方孔中。

I didn't want to type this up as an answer, because it doesn't answer your question directly, but based on your comment in response to my comment to your question, it merits some explanation.

Enums are meant to be very simple type safe representations of state. If you simply use constants, then you can assign the wrong constants to a value. This prevents you from assigning the wrong type of constant to a field. For example, if you have something that expects DayOfWeek, you can't assign a FileAccess value, even though they are both constants of the same underlying type.

DayOfWeek day = FileAccess.Write; // doesn't work

If you need this type safety and you don't need for your enum to exhibit any other type of behavior, then use an enum. If you are concerned with having your enum do other things as well (such as enumeration, mathematical operations, etc) then you should consider using classes. See my example below.

public class LegalShipTypes
{
    private readonly byte _numericValue;
    private readonly string _text;

    private LegalShipTypes(byte numericValue, string text)
    {
        _numericValue = numericValue;
        _text = text;
    }

    public byte Value { get { return _numericValue; } }
    public string Text { get { return _text; } }

    public static IEnumerable<LegalShipTypes> All
    {
        get
        {
            return new[] { Frigate, Cruiser, Destroyer, Submarine, AircraftCarrier };
        }
    }

    public static readonly LegalShipTypes Frigate = new LegalShipTypes(1, "Frigate");
    public static readonly LegalShipTypes Cruiser = new LegalShipTypes(2, "Cruiser");
    public static readonly LegalShipTypes Destroyer = new LegalShipTypes(3, "Destroyer");
    public static readonly LegalShipTypes Submarine = new LegalShipTypes(4, "Submarine");
    public static readonly LegalShipTypes AircraftCarrier = new LegalShipTypes(5, "Aircraft Carrier");
}

Now you can use it in a typesafe way like this:

public class Fleet
{
    private readonly List<LegalShipTypes> _ships;

    public Fleet()
    {
        _ships = new List<LegalShipTypes>();
    }

    public LegalShipTypes Flagship { get; set; }
    public ICollection<LegalShipTypes> Ships { get { return _ships; } }
}

....

var fleet = new Fleet();
fleet.FlagShip = LegalShipTypes.AircraftCarrier;
var iDoNotKnowWhyYouWouldNeedThisBut = LegalShipTypes.All.Sum(ship => ship.Value);
Console.WriteLine("The flagship is a(n) \"{0}\".", fleet.FlagShip.Text);
if (fleet.FlagShip == LegalShipTypes.AircraftCarrier) // this will work because it's a reference comparison
    Console.WriteLine("This should be true");

As you can see, you still have type safety, but much more flexibility. It is more code, but you won't find yourself working against the limitations of enum. To reiterate, enum is meant to be simple. It's supposed to be simple. If your needs are simple, don't hesitate to use it. If your needs are more complex, there's no shame in using good old fashioned object oriented programming to solve your problem.

EDIT

In light of your last comment response that the byte values represents the number of pegs, I would highly recommend you don't use enums to solve your problem. You'd be (ironically) trying to put a round peg in a square hole.

世界如花海般美丽 2024-08-27 23:55:35

假设它是一个继承自 System.Int32 的枚举(这是默认值),请尝试以下操作。

public int Sum(Type enumType) {
  return Enum.GetValues(enumType).Cast<int>().Sum();
}

编辑没有注意到OP的问题继承自byte。这是一个适用于 byte 的版本

public int Sum(Type enumType) {
  return Enum.GetValues(enumType).Cast<byte>().Select(x => (int)x).Sum();
}

Try the following assuming it's an enum that inherits from System.Int32 (this is the default).

public int Sum(Type enumType) {
  return Enum.GetValues(enumType).Cast<int>().Sum();
}

EDIT didn't notice the OP's question inherits from byte. Here's a version that works with byte

public int Sum(Type enumType) {
  return Enum.GetValues(enumType).Cast<byte>().Select(x => (int)x).Sum();
}
羁〃客ぐ 2024-08-27 23:55:35

请参阅此类似问题的已接受答案:

How do I enumerate an enum?

您可以获取值,枚举它们,然后在 for 循环中对值求和。

See the accepted answer of this similar question:

How do I enumerate an enum?

You could get the values, enumerate through them and just sum the values in the for loop.

二智少女猫性小仙女 2024-08-27 23:55:35

如果您想对枚举器值求和,那么使用带标记的枚举器不是更好吗?

If you want to be summing enumerator values, wouldn't you be better off using a flagged enumerator?

心清如水 2024-08-27 23:55:35

JaredPar 答案的通用版本与卢克的更正:

public int Sum<T>(Type enumType) {
    return Enum.GetValues(enumType).Cast<T>().Sum();
}

致电:

Sum<byte>(typeof(LegalShipTypes));

编辑:
好吧,放弃这个想法。我想:

public int Sum(Type enumType) {
    return Enum.GetValues(enumType).Cast<byte>().Sum();
}

就是答案。

A generic version of JaredPar's answer with Luke's correction:

public int Sum<T>(Type enumType) {
    return Enum.GetValues(enumType).Cast<T>().Sum();
}

Call with:

Sum<byte>(typeof(LegalShipTypes));

EDIT:
Well, scratch that idea. I suppose:

public int Sum(Type enumType) {
    return Enum.GetValues(enumType).Cast<byte>().Sum();
}

is the answer.

雨落□心尘 2024-08-27 23:55:35
 public enum LegalShipTypes : byte
    {
        Frigate = 1,
        Cruiser = 2,
        Destroyer = 3,
        Submarine = 4,
        AircraftCarrier = 5
    }
    class Program
    {
        static void Main()
        {
            byte sum = 0;
            foreach (byte item in Enum.GetValues(typeof(LegalShipTypes)))
            {
                sum += (byte)(object)item;
            }

            Console.WriteLine(sum);
        }
    }
 public enum LegalShipTypes : byte
    {
        Frigate = 1,
        Cruiser = 2,
        Destroyer = 3,
        Submarine = 4,
        AircraftCarrier = 5
    }
    class Program
    {
        static void Main()
        {
            byte sum = 0;
            foreach (byte item in Enum.GetValues(typeof(LegalShipTypes)))
            {
                sum += (byte)(object)item;
            }

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