Enum with decimal values or some like this - c#

Basically I want to define an enum with decimal values but this is not possible. An alternative is:
public static class EstadoRestriccion
{
public const decimal Valur1 = 0;
public const decimal Value2 = 0.5M;
public const decimal Value3 = 1;
};
But I need add these constants in a combobox where the options to display should be the name of constants and SelectedItem should return the value (0, 0.5M, 1) or some like these. I know that it is possible but it is ugly.
With an enum I can do this easly: comboBox.DataSource = Enum.GetValues(typeof(MyEnum));
What is the best way to simulate an enum with my requirements?

A dictionary may be a good choice.
Dictionary<string,decimal> could be a good candidate - letting you name the values.
var values = new Dictionary<string,decimal>();
values.Add("Value1", 0m);
values.Add("Value2", 0.5m);
values.Add("Value3", 1m);
This can be wrapped in a class so you only expose a getter by index, instead of the whole Dictionary<TKey,TValue> interface.

THERE IS NO WAY simply. enum accepts only integer values. The code snippet you put is good.
There is a small difference between const decimal and static readonly decimal. The first is direct evaluation; the compiler replaces the name with its value. In contrast, readonly inforces the code to refer to the field each time and bring the value from it. You can observe why readonly is being used with reference types while const cannot be (expect for a string).

You could change your class slightly:
public class EstadoRestriccion
{
public static readonly EstadoRestriccion Value1 = new EstadoRestriccion("Value1", 0);
public static readonly EstadoRestriccion Value2 = new EstadoRestriccion("Value2", 0.5M);
public static readonly EstadoRestriccion Value3 = new EstadoRestriccion("Value3", 1);
private static readonly EstadoRestriccion[] values = new EstadoRestriccion[] { Value1, Value2, Value3 };
private string name;
private decimal value;
private EstadoRestriccion(string name, decimal value)
{
this.name = name;
this.value = value;
}
public static EstadoRestriccion[] GetValues()
{
return values;
}
public override string ToString()
{
return this.name;
}
};
And some decimal conversion and/or change value to be a public property.

How about a static readonly array of decimal?
public static readonly decimal[] myValues = new[] {0, 0.5M, 1};

Related

Create a method which return a list of parameters (const string) from a class

I'm developing a class which contains some const strings
public static class Constants
{
public const string CarID= "car_id";
//public const string NumberID= "number_id"; // this is the second const string might be added, so
//the new created function can return the two
}
public class CarENParameters
{
public string Params { get; set; }
public CarENParameters(string carId)
{
Params = carId;
}
}
public static class CarPropertyProcess
{
//test params
public static CarENProps Parse(Uri uri,string content)
{
string carID= Regex.Matches(content, #"\$\('#CarXL'\)\.val\((\d+)\)", RegexOptions.None)[0].Groups[1].Value;
var parameters = new Dictionary<string, string>
{
{Constants.CarID, carID},
};
return new CarENProps(uri.AbsoluteUri, parameters);
}
public static CarENParameters GetParameters()
{
return new CarENParameters(Constants.CarID);
}
}
In the class Constants, I have one carID, now the case is it might have more than one const string like : public const string NumberID= "number_id";
So I want to create one function to return a list of those const strings, which are car_id and number_id with a class name CarENParameters but I havent figured out how to return a list by a get/set in a class, should I use dictionary or keyvaluespair to achieve that ? I'm quite new to C# so hope that I can have a better point of view from the helps of you guys. Thanks
Are you looking for something like this:
public static List<CarENParameters> GetParameters()
{
return new List<CarENParameters>()
{
new CarENParameters(Constants.CarID1),
new CarENParameters(Constants.CarID2),
new CarENParameters(Constants.CarID3)
}
}
You can use reflection for this
don't forget to put using System.Reflection;
// get class type
Type type = typeof(Constants);
// get a list of fields
FieldInfo[] fields = type.GetFields();
List<CarENParameters> list = new List<CarENParameters>();
// loop on field list
foreach (FieldInfo field in fields)
{
// if field is a string add it to our return list
if (field.FieldType == typeof(String))
list.Add(new CarENParameters((String) field.GetValue(null)));
}

Working nicely with Enums and HEX values

I have a list of enums as follows:
public enum EventID : uint
{
SAMPLE_EVENT_1 = 0xDCCA0000,
SAMPLE_EVENT_2 = 0xDCCB0001,
SAMPLE_EVENT_3 = 0xDCCA0002,
SAMPLE_EVENT_4 = 0xDCC00003,
SAMPLE_EVENT_5 = 0xDCCA0004,
...
}
The hex value for each enum is deciphered as follows:
/// DCC X XXXX
/// --- - ----
/// | | |--> Notification ID (0x0000 to 0xFFFF)
/// | |-----> Notification Type (0x0 to 0xA)
/// |--------> Sub-system ID (0xDCC)
What is the best way to assign values to the enum's, such that adding enum's later won't mean reassigning all the values. The only Sub-system ID, and Notification Type are chosen, the Notification ID should be automatically assigned.
For example, it might get annoying if there were thousands of enum's and I had to number them by hand or renumber them if adding an enum in the middle.
Thanks.
If you asked me, you shouldn't be encoding this data in your enum values. It would be better to apply attributes the them instead where you could get this information. Let the actual value of the enum represent the NotificationId to get the automatically assigned values.
[AttributeUsage(AttributeTargets.Field, AllowMultiple=false)]
public class SubsystemIdAttribute : Attribute
{
public SubsystemIdAttribute(ushort value)
{
this.Value = (ushort)(value & 0xFFF);
}
public ushort Value { get; private set; }
}
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class NotificationTypeAttribute : Attribute
{
public NotificationTypeAttribute(byte value)
{
this.Value = (byte)(value & 0xF);
}
public byte Value { get; private set; }
}
public enum EventId
{
[SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_1,
[SubsystemId(0xDCC)] [NotificationType(0xB)] SAMPLE_EVENT_2,
[SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_3,
[SubsystemId(0xDCC)] [NotificationType(0x0)] SAMPLE_EVENT_4,
[SubsystemId(0xDCC)] [NotificationType(0xA)] SAMPLE_EVENT_5,
}
public static class EventIdExtensions
{
public static ushort GetSubsystemId(this EventId eventId)
{
return GetAttributeValue(eventId, (SubsystemIdAttribute a) => a.Value);
}
public static byte GetNotificationType(this EventId eventId)
{
return GetAttributeValue(eventId, (NotificationTypeAttribute a) => a.Value);
}
private static TValue GetAttributeValue<TAttribute, TValue>(EventId eventId, Func<TAttribute, TValue> selector)
where TAttribute : Attribute
{
return typeof(EventId).GetField(eventId.ToString())
.GetCustomAttributes(false)
.OfType<TAttribute>()
.Select(selector)
.Single();
}
}
To get the values of the attributes, call the appropriate extension methods.
var eventId = EventId.SAMPLE_EVENT_3;
var subsystemId = eventId.GetSubsystemId(); // 0xDCC
var notificationType = eventId.GetNotificationType(); // 0xA
Enums only auto-increment by 1, so you'd have to keep them in order by sub-system, then notification type, then notification id, and only when there are gaps would you assign. So to keep order proper, your above enum would look like this:
public enum EventID : uint
{
SAMPLE_EVENT_1 = 0xDCCA0000,
SAMPLE_EVENT_3 = 0xDCCA0002,
SAMPLE_EVENT_5 = 0xDCCA0004,
SAMPLE_EVENT_2 = 0xDCCB0001,
SAMPLE_EVENT_4 = 0xDCC00003,
}
I guess that purpose of your enums is to give a names to the events with specific codes. The question is what is the canonical source of association between names and codes. If it is you (or your code) I don't see any reason to renumber. If it comes from some external source (e.g. documentation) try to deploy some code generation (e.g. T4 templates).
If you are happy with Jeff's answer this is imho much more cleaner design
public class EventId
{
public static readonly SAMPLE_EVENT_1 = new EventId(0xDCC, 0xA);
public static readonly SAMPLE_EVENT_2 = new EventId(0xDCC, 0xA);
public static readonly SAMPLE_EVENT_3 = new EventId(0xDCC, 0xA);
public static readonly SAMPLE_EVENT_4 = new EventId(0xDCC, 0xA);
public readonly ushort SubSystemId;
public readonly byte NotificationType;
public readonly ushort NotificationId;
private static ushort notificationCounter = 0;
private EventId(ushort subSystemId, byte notificationType)
{
this.SubSystemId = subSystemId;
this.NotificationType= notificationType;
this.NotificationId = notificationCounter++;
}
}
But of course you creating dependency between compiler and NotificationId which you probably don't like.

string representation of an enum (estring)?

i need an enum or something similiar to do something like this:
public enum MyStringEnum {
[StringValue("Foo A")] Foo = "A",
[StringValue("Foo B")] Foo = "B" }
is this possible? my example, i return back a dataset with a value represented as either A,B,C,D,E .. i need a solution to return this as a string representation?
i guess the obvious would be to create an extension method or something which just had a switch statement in and return a string .. any other cleaner solutions?
regards,
dave
Here is something we use for our MVC applications to retrieve a display name for our enums. It uses a custom attribute and an extension method to retrieve the enum display name.
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class EnumDisplayNameAttribute : Attribute
{
public EnumDisplayNameAttribute(string displayName)
{
DisplayName = displayName;
}
public string DisplayName { get; set; }
}
public static string GetDisplayName(this Enum enumType)
{
var displayNameAttribute = enumType.GetType()
.GetField(enumType.ToString())
.GetCustomAttributes(typeof(EnumDisplayNameAttribute), false)
.FirstOrDefault() as EnumDisplayNameAttribute;
return displayNameAttribute != null ? displayNameAttribute.DisplayName : Enum.GetName(enumType.GetType(), enumType);
}
Usage on the enum:
public enum Foo
{
[EnumDisplayName("Foo Bar")]
Bar = 0
}
Getting back the display name:
var f = Foo.Bar;
var name = f.GetDisplayName();
Would it be an option not to use enum and use structs instead?
struct FooEnum
{
private int value;
private string name;
private FooEnum(int value, string name)
{
this.name = name;
this.value = value;
}
public static readonly FooEnum A = new FooEnum(0, "Foo A");
public static readonly FooEnum B = new FooEnum(1, "Foo B");
public static readonly FooEnum C = new FooEnum(2, "Foo C");
public static readonly FooEnum D = new FooEnum(3, "Foo D");
public override string ToString()
{
return this.name;
}
//TODO explicit conversion to int etc.
}
You could then use FooEnum like an enum with an own ToString() overload:
FooEnum foo = FooEnum.A;
string s = foo.ToString(); //"Foo A"
If you want to do something like this:
MyStringEnum value = MyStringEnum.A;
string description = value.GetDescription();
// description == "Foo A"
Setup your enum like this:
public enum MyStringEnum
{
[Description("Foo A")]
A,
[Description("Foo B")]
B
}
And use a utility/extension method that reads the attribute:
public static string GetDescription(this MyStringEnum enumerationValue)
{
Type type = enumerationValue.GetType();
string name = enumerationValue.ToString();
//Tries to find a DescriptionAttribute for a potential friendly name for the enum
MemberInfo[] member = type.GetMember(name);
if (member != null && member.Length > 0)
{
object[] attributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attributes[0]).Description;
}
}
return name;
}
I've seen this done where I would put
MyStringEnum.Foo.ToString();
In this case it would give "A"
The cleanest solution for this problem is to create a custom attribute that will store the string value you want for the enum constant. I've used that strategy in the past and it worked out fairly well. Here's a blog post detailing the work involved:
Enum With String Values In C# - Stefan Sedich's Blog
Of course this is only necessary if you need some kind of meaningful text. If the name of the enum constant works for you...then you can simply call ToString().

C# enum addition

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

Developing a Products Class with a nested class .Net

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

Categories

Resources