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.
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)));
}
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.
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();
}
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.
If you want to be summing enumerator values, wouldn't you be better off using a flagged enumerator?
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.
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);
}
}
Related
I want to access three members of a class (_orderDay, _orderCustody, _orderBox) according to and indexing variable (orderIndex), using a different approach than in the following example
public class COrdering
{
private int _orderDay;
private int _orderCustody;
private int _orderBox;
public COrdering() { _orderDay = _orderCustody = _orderBox = 0; }
public int IncOrder(int orderIndex)
{
int v = orderIndex == 0 ? _orderDay : (orderIndex == 1 ? _orderCustody : _orderBox);
v++;
if (orderIndex == 0) _orderDay = v
else if (orderIndex == 1) _orderCustody = v;
else _orderBox = v;
return v;
}
}
The idea is to use less coding than in the previous example. When I coded something like this in C++ I used std::bind to create a const array of references to each field involved, but I don't know how to make something similar in C#. Can anyone help me out with this?
EDIT
I've found a way to optimize IncOrder method:
//...
private int _incDay() { return ++_orderDay; }
private int _incCustody() { return ++_orderCustody; }
private int _incBox() { return ++_orderBox; }
private IReadOnlyList<Func<int>> _funcs = Array.AsReadOnly(new Func<int>[] {_incDay, _incCustody, incBox});
public int IncOrder(int orderIndex) { return _funcs[orderIndex](); }
There may be another way, such as creating an array of references to these fields, but I don't know if that's possible.
Sounds like a job for an index operator overload:
public int this[int index] => IncOrder(index);
Usage:
COrdering ordering = new COrdering();
int newValue = ordering[0];
Updated - you can use an array internally
public class COrdering
{
public enum OrderIndex { Day = 0, Custody = 1, Box = 2, NumElements };
private readonly int[] values = new int[(int)OrderIndex.NumElements];
public int IncOrder(OrderIndex orderIndex) => ++values[(int)orderIndex];
public int this[OrderIndex index] => IncOrder(index);
}
Also, your constructor can be removed, in C# everything is auto initialized to 0 (or null for reference types).
Why not use a Dictionary<int, int>?
public class COrdering
{
Dictionary<int, int> map = new Dictionary<int, int>();
public COrdering() { map[0] = 0; map[1] = 0; map[2] = 0; }
public int IncOrder(int orderIndex)
{
return ++map[orderIndex];
}
}
In fact you can even use an int[] or a List<int>.
I understand you want to simplify your code, so in that case start by the variables where you save data, if you are accessing them by index it would make more sense to declare an array and use an enum, something like this:
public class COrdering
{
enum OrderType
{
Day = 0,
Custody = 1,
Box = 2,
Count = 3
};
private int[] _order = new int[(int)OrderType.Count];
public int IncOrder(OrderType orderIndex)
{
// Increment corresponding order type and return its value
return ++_order[(int)orderIndex];
}
}
You can see that you implement your IncOrder with just one line of code. The ++ must be before the variable name, so you get the correct answer. I either use an intermediate variable for the increment or a ++ preceded of a good comment, so that the next programmer will see it.
The other solution with [] overload is unexpected and surprising for the next guy debugging your code :-) so that being said I suppose you guess which one I'd chose.
I'm trying to create a function that takes two player classes, compares which AttackElement they used, and is able to alter each class' variables based on which AttackElement has a better advantage.
I'm sure there's a much more logical way of doing this, but at the moment I'm stuck wondering if I could concatenate a string to call the correct variable. For example, if I am trying to access a variable in a player class called WaterStrength can I simply have a string that combines the word "Water" with "Strength" in order to call the variable? I know calling functions/variables doesn't normally work that way, but in this example I'm calling this iWantToCombineThis.
int baseDamage = 2;
class PlayerClass(){
int Health = 10;
int WaterStrength = 1;
int FireStrength = 1;
}
void AnalyzeRound(PlayerClass won, PlayerClass lost, string winningElement)
{
string iWantToCombineThis = winningElement + "Strength";
lost.Health -= baseDamage * won.iWantToCombineThis;
}
AnalyzeRound(Player1,Player2,"Water");
AnalyzeRound(Player2,Player1,"Fire");
A better approach would be to make the strength type an enum:
public enum StrengthType
{
Water=1,
Fire=2
}
And then have a method on the player class to get the Strength value for a given type from a dictionary mapping strength types to int values:
private Dictionary<StrengthType, int> strengthTypes = new Dictionary<StrengthType, int>
{
[StrengthType.Water] = 12,
[StrengthType.Fire] = 15
};
public int GetStrength(StrengthType strengthType)
{
return strengthTypes[strengthType];
}
You could use a Dictionary<string, Func<PlayerClass, int>> to get the value without resorting to reflection. Try this:
int baseDamage = 2;
class PlayerClass
{
public int Health = 10;
public int WaterStrength = 1;
public int FireStrength = 1;
}
private Dictionary<string, Func<PlayerClass, int>> indirect = new Dictionary<string, Func<PlayerClass, int>>()
{
{ "WaterStrength", pc => pc.WaterStrength },
{ "FireStrength", pc => pc.FireStrength },
};
void AnalyzeRound(PlayerClass won, PlayerClass lost, string winningElement)
{
int strength = indirect[winningElement + "Strength"](won);
lost.Health -= baseDamage * strength;
}
Disclaimer: As the comments have noted, this is kind of an anti pattern and consider doing it statically.
But to answer your question, you could use reflection to do this:
public static class Utility
{
static T GetDynamicValue<T>(this Object obj, string propertyName)
{
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
var prop = obj.GetType().GetProperty(propertyName, flags);
var val =prop.GetValue(obj);
return (T)val;
}
}
And then you can say:
var x = won.GetDynamicValue<int>("iWantToCombineThis");
lost.Health -= baseDamage * x;
I have an enum like this:
enum myEnum
{
a = 0101,
b = 2002,
c = 0303
}
I try to get enum value with casting but the 0 at the begin of my enums was removed.
For example I tried this:
var val = (int)myEnum.a;
How can get enum value as string when we have 0 at the beginning of it?
You should rethink your design, but if you want to check your enum integers to a given string, you can use .ToString("0000") to get the string "0101" out of the integer 101.
First, enums are integers, since as their name says, they are enumerations and an enumeration, they are numbers, so enum is integer.
Secondly, you must bear in mind that zero is a null value, since the system is a 01 or 001 like 1, since (basic mathematics) a zero to the left is worthless, so this code is incorrect.
enum myEnum
{
a=0101,
b=2002,
c=0303,
}
The correct way is
enum myEnum
{
a = 0,
b = 1,
c = 2
}
Where the zero is alone, so the system sees it as an index
Now with this, you should only use one of the conversion processes of C#
string strOne = ((myEnum)0).ToString();
string strTwo = ((myEnum)1).ToString();
string strThree = ((myEnum)2).ToString();
Read the MSDN reference https://msdn.microsoft.com/en-us/library/16c1xs4z(v=vs.110).aspx
Enumeration values are always integers. If you need to associate a string with an enumeration value, you can use a dictionary:
enum myEnum { a, b, c }
Dictionary<myEnum, string> lookup = new Dictionary
{
{ a, "0101" },
{ b, "2002" },
{ c, "0303" }
};
To get the string associated with a particular value just use this:
var s = lookup[myEnum.a]; // s = 0101
Another common way to handle this sort of problem is simply to use constants.
class MyConstants
{
public const string a = "0101";
public const string b = "2002";
public const string c = "0303";
}
var s = MyConstants.a; // s = 0101
Try using formatting: you want 4 digits and that's why you can put d4 format string. In order to hide all these implmentation details (cast and formatting) let's write an extension method:
enum myEnum {
a = 0101,
b = 2002,
c = 0303
}
static class myEnumExtensions {
public static string ToReport(this myEnum value) {
return ((int)value).ToString("d4"); // 4 digits, i.e. "101" -> "0101"
}
}
...
myEnum test = myEnum.a;
Console.Write(test.ToReport());
If you always need a specific number of digits you could use string format to get the leading zeros:
var str = String.Format("{0:0000}", (int)myEnum.a);
Or, shorter:
var str = $"{(int) myEnum.a:D4}";
Alternative:
Use an attribute to add extra information to an enum
Attribute:
public class DescriptionAttribute : Attribute
{
public string Name { get; }
public DescriptionAttribute(string name)
{
Name = name;
}
}
Enum:
enum myEnum
{
[Description("0101")]
a = 101,
[Description("2002")]
b = 2002,
[Description("303")]
c = 303
}
Extension Method:
public static string GetDescription(this myEnum e)
{
var fieldInfo = e.GetType().GetField(e.ToString());
var attribute = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).FirstOrDefault() as DescriptionAttribute;
return attribute.Name;
}
Usage:
var name = myEnum.a.GetDescription() //will return '0101'
Assuming that the numbers in your enum always have a length of 4
you can use the following
var val = (int)myEnum.a).ToString().PadLeft(4, '0')
I would like an advice. My project have a lot of equals methods with different values, and i would like to do a single method that does the same.
The methods are this:
private void Enum1()
{
Console.WriteLine(Enum.GetValue(ENUM1.Code));
Console.WriteLine(Enum.GetValue(ENUM1.Info));
}
private void Enum2()
{
Console.WriteLine(Enum.GetValue(ENUM2.Code));
Console.WriteLine(Enum.GetValue(ENUM2.Info));
}
private void Enum3()
{
Console.WriteLine(Enum.GetValue(ENUM3.Code));
Console.WriteLine(Enum.GetValue(ENUM3.Info));
}
This is the enums:
public enum ENUM1
{
Code = 1,
Info = 3
}
public enum ENUM2
{
Code = 91,
Info = 4
}
public enum ENUM3
{
Code = 6,
Info = 27
}
There is only a way to create a method by inserting the input type of enum to use? maybe a similar solution of this:
private void General("ENUM1")
{
var type = ENUM1;
switch (p)
{
case "ENUM1":
type = ENUM1;
case "ENUM2":
type = ENUM2;
case "CASALINGHI":
type = ENUM3;
default:
type = ENUM1;
}
Console.WriteLine(Enum.GetValue(type.Code));
Console.WriteLine(Enum.GetValue(type.Info));
}
I think something like this is what you are looking for:
private void General<T>()
{
var values = Enum.GetValues(typeof(T));
foreach(var value in values)
Console.WriteLine(value);
}
General<Enum1>();
General<Enum2>();
General<Enum3>();
Or this, depending on how you want to use it:
private void General(Type enumType)
{
var values = Enum.GetValues(enumType);
foreach(var value in values)
Console.WriteLine(value);
}
General(typeof(Enum1));
General(typeof(Enum2));
General(typeof(Enum3));
Why do you keep using enums, when you can easily use classes? Read more about Object-Oriented programming.
Create a single class:
public class MyEnum
{
public int Code
{
get; set;
}
public int Info
{
get; set;
}
public string Display()
{
Console.WriteLine(this.Code);
Console.WriteLine(this.Info)
}
//
// This will keep your enums static, available from any method
//
private static List<MyEnum> _globals = new List<MyEnum();
public static List<MyEnum> Globals ()
{
if (this._globals.Count == 0)
{
this._globals.Add(new MyEnum(){ Code = 1, Info = 3 });
this._globals.Add(new MyEnum(){ Code = 91, Info = 4 });
this._globals.Add(new MyEnum(){ Code = 6, Info = 27 });
}
return this._globals;
}
}
After this you can easily print out all the enums with the following code:
foreach (MyEnum* en in MyEnum.Globals())
{
en.Display();
}
Please look into solutions similar to this one, since your enum's obviously represent some data.
I am looking for help in determining if the class model that I am building can be improved upon. The class that I am building is a simple Product class with a few attributes.
class clsProducts
{
private string _name;
private double _productionRate;
//Constructor
public clsProducts()
{
_name = "null";
_productionRate = 0.0;
}
public clsProducts(string name, double productionRate)
{
_name = name;
_productionRate = productionRate;
}
//Properties
public string Name
{
get { return _name; }
}
public double ProductionRate
{
get { return _productionRate; }
}
}
What I would like to add is the ability to have the monthly forecasted values for each product in the class. I could add the following to do this
private double _janValue;
private double _febValue;
and so on, but this seems messy. I also considered creating a nested class called ForecastValues, such as
class clsProducts
{
...code here....
protected class ForecastValues
{
private string name;
private double forecastValue;
...other code.....
}
}
however, I am not sure that this idea would even work. Can any one suggest a way for me to handle this cleanly?
Thank you
A few things here.
I would recommend removing the cls hungarian prefix from the class name.
Depending on exactly what your "ForecastValues" are. You could make a property on the "Product" class that is a List, or possibly a Dictionary. My guess is that you might be able to go the dictionary route with ease.
I would suggest just to use an array and an indexer.
public enum Month
{
January = 1, February = 2, March = 3,
April = 4, May = 5, June = 6,
July = 7, August = 8, September = 9,
October = 10, November = 11, December = 12
}
public class Product
{
private readonly String name = null;
private readonly Double productionRate = 0.0;
private readonly Double[] productionRateForcast = new Double[12];
public Product(String name, Double productionRate)
{
this.name = name;
this.productionRate = productionRate;
}
public String Name { get { return this.name; } }
public Double ProductionRate { get { return this.productionRate; } }
public Double this[Month month]
{
get { return this.productionRateForcast[month - Month.January]; }
set { this.productionRateForcast[month - Month.January] = value; }
}
}
I am not sure if month - Month.January requires an explicit cast to Int32. Alternativly one could start with January = 0 but this seems a bit odd, too.
I did also some code changes. I removed the default constructor, because I see no value in a Product instance with "uninitialized" fields and no possibilty to alter them later. In consequence I made the fields readonly, too. Finaly I removed the Hungarion notation prefix - this is a quite an outdate coding style - and turned Products into Product because it represents one product not a collection of products.
UPDATE
To catch up the dictionary idea .... I will just give the required changes.
private readonly IDictionary<Month, Double> productionRateForcast =
new Dictionary<Month, Double>();
public Double this[Month month]
{
get { return this.productionRateForcast[month]; }
set { this.productionRateForcast[month] = value; }
}
This might be a even cleaner solution then using an array. You could also just expose the dictionary through a property instead of having an indexer, but I consider the indexer a cleaner solution because it hides some implementation details.
public IDictionary<Month, Double> ProductionRateForcast
{
return this.productionForecast;
}
In all case the usage would be as follows.
Product myProduct = new Product("Great Product", 0.8);
myProduct[Month.August] = 0.7;
This looks quite odd. One could try adding a IndexerNameAttribute to the indexer, but I am not sure if this would allow to write
myProduct.ProductionValueForcast[Month.August] = 0.7;
in a language with indexer support. So I finally tend to change my mind and prefer exposing the dictionary by a property if the IndexerNameAttribute does not help.
I don't think nested classes are a great idea. What I would do is create an additional class 'ForecastValues' but mark it as 'internal protected'. That way you can use it within your assembly but users of your code will only be able to reference it when it contains values.
-Shaun
This is what I would do,
class ClsProducts
{
//Constructor
public ClsProducts()
{
Name = "null";
ProductionRate = 0.0;
}
public ClsProducts(string name, double productionRate)
{
Name = name;
ProductionRate = productionRate;
}
//Automatic properties with private setters
public string Name { get; private set; }
public double ProductionRate { get; private set; }
//since you basically have key value pair, why not use one?
public KeyValuePair<String,Double> Forcast{ get; set; }
}