I may miss some sort of point here, if that's the case - please include that discussion as a part of my question :).
This is a shortened down and renamed sample of a working code. The GetTicks(…) is a single sample, which could be any sort of functionality (value of > 0 < 9 should return a specific Enum a.so).
public static class Something
{
public enum TypeOf : short
{
Minute = 2, Hour = 3, Day = 4, …
}
public static long GetTicks(Something.TypeOf someEnum)
{
long ticks = 0;
switch (someEnum)
{
case Something.TypeOf.Minute:
ticks = TimeSpan.TicksPerMinute;
break;
case Something.TypeOf.Hour:
ticks = TimeSpan.TicksPerHour;
break;
....
}
return ticks;
}
}
// This class is called from anywhere in the system.
public static void SomeMethod(string dodo, object o, Something.TypeOf period)
{
// With the design above
long ticks = Something.GetTicks(period);
// Traditional, if there was a simple enum
if (period == Something.Day)
ticks = TimeSpan.FromDays(1).Ticks;
else if (period == Something.Hour)
ticks = TimeSpan.FromHours(1).Ticks;
}
The idea is to collect functionality that concerns an enum, near as possible to the enum itself. The enum is the reason function. Also, I find it easy and natural to look for such functionality near the enum. Also, it's easy to modify or extend.
The drawback I have is that I have to state the enum more explicit, like Something.TypeOf. The design may look non-standard? And would it apply, if the enum was for internal use in the class.
How would you do this more nicely?
I tried abstract, base inheritance, partial. None of them seem to apply.
If you don't mind a little more writing you can make extension methods to expand the interface of the enum.
e.g.
public enum TimeUnit
{
Second,
Minute,
Hour,
Day,
Year,
/* etc */
}
public static class TimeUnitExtensions
{
public static long InTicks(this TimeUnit myUnit)
{
switch(myUnit)
{
case TimeUnit.Second:
return TimeSpan.TicksPerSecond;
case TimeUnit.Minute:
return TimeSpan.TicksPerMinute;
/* etc */
}
}
}
This can add "instance" methods to your enums. It's a bit more verbose than mostly liked, though.
Remember though that an enum should be treated mostly as a named value.
C# enums don't work well like this. However, you can implement your own "fixed set of values" fairly easily:
public sealed class Foo
{
public static readonly Foo FirstValue = new Foo(...);
public static readonly Foo SecondValue = new Foo(...);
private Foo(...)
{
}
// Add methods here
}
As it happens, one example I've got of this is remarkably similar to yours - DateTimeFieldType in Noda Time. Sometimes you might even want to make the class unsealed, but keep the private constructor - which allows you to create subclasses only as nested classes. Very handy for restricting inheritance.
The downside is that you can't use switch :(
Related
I'm thinking what is the best way to compare values from two different enums.
Example:
public enum ExampleEnumA
{
ExampleValue
}
public enum ExampleEnumB
{
ExampleValue
}
if (ExampleEnumA.ExampleValue.ToString() == ExampleEnumB.ExampleValue.ToString())
{
}
Comparing strings work, but I know that it's not the most efficient and eligent way. How it can be done better?
EDIT:
Maybe it's a design flaw, but it's problem from a real project, not my incorrect understanding of enums. This is how it looks like and there was no time to refactor whole approach.
public interface IProvider
{
Enum SectionType { get; }
}
public class FirstProvider : IProvider
{
public Enum SectionType
{
get { return ExampleEnumA.ExampleValue; }
}
}
public class SecondProvider : IProvider
{
public Enum SectionType
{
get { return ExampleEnumB.ExampleValue; }
}
}
public class Program
{
public void TmpMethod(Enum sectionType)
{
var provider = GetFromIoC...
if (provider.SectionType == sectionType)
{
//...
}
}
}
Enumerations are like an abstraction layer on top a regular class of integer-based constants.
That abstraction includes evaluating false even if two enumeraiton values are the same integer but belong to different enumeration types.
What's the best way of comparing two different enumeration types with same underlying value? I would answer that it should be a design flaw if you need to perform this evaluation.
For example, let's say we've implemented these enumerations:
public enum States
{
Open = 1,
Closed
}
public enum SpecialFolders
{
ProgramFiles86 = 1,
ProgramFiles64
}
Would make sense something like States.Open == SpecialFolders.ProgramFiles86? Potentially, they seem to be equal (they won't) because both enumeration values have an underlying value of 1, but 1 doesn't mean the same if the enumeration type isn't the same.
It's like saying that...
Bread
Meat
...is the same as:
Steal (Bread == Steal????????????)
Wood
Maybe...
...you can defeat the purpose of typing constants as enumerations casting them to int:
if ((int)ExampleEnumA.ExampleValue == (int)ExampleEnumB.ExampleValue)
{
}
...if the underlying type is int. It could also be long:
public enum SomeEnum : long
{
}
...and you would need to cast left and right part of your evaluation to long, and so on.
Anyway, I insist that you shouldn0t go this way. Maybe you should use a regular class of constants instead and you'll avoid 2 casts per evaluation:
public static class States
{
public const int Open = 1;
public const int Closed = 2;
}
public static class Materials
{
public const int Steel = 1;
public const int Wood = 1;
}
// true! but not that true... I can't understand why these constants equal...
if(States.Open == Materials.Wood)
{
}
BTW, I still consider this a design flaw and you should avoid not using enumerations to workaround a bad design decision.
Imagine you have two tables - Orders and OrderStates - and the obvious relationship that every Order is in a particular state. Let's say that both have a int primary key Id. The order states will never change and are in database for only design and ui purposes. That being said you would want to create an Enum type representing the order states. However, the entity framework has already generated classes using the order state int value/key.
What are the possible solutions for given problem? Remeber that the question is about EF1 or EF .NET 3.5 if you will and that you start with a already designed database (database first approach). I work with the old version because I am currently developing an application for Sharepoint 2010 which runs on .NET 3.5.
I have only found solutions for EF4 or higher like this one:
Enum Support for Entity Framework Database First
To make it clearer, I would like to avoid casting the int all the time. The generated code forces you to write either:
(OrderStates)OrderState.State == OrderState.StateX;
OR
OrderState.State == (int)OrderState.StateX;
It could be ok in case you get to such a situation just once, but that is usually not the case. Also the enum's code readability is higher than just some int value.
Alright, so you can't overload the operators on an enum. However, you could build a class that overloads the operators you could go both ways. Consider the following code:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(1 == MyEnum.Value0);
Console.WriteLine(2 == MyEnum.Value2);
}
}
public class MyEnum
{
public static readonly MyEnum Value0 = 0;
public static readonly MyEnum Value1 = 1;
public static readonly MyEnum Value2 = 2;
private MyEnum() { }
private int _val;
private MyEnum(int val)
{
_val = val;
}
public static implicit operator int(MyEnum val)
{
return val._val;
}
public static implicit operator MyEnum(int val)
{
return new MyEnum(val);
}
}
This outputs:
False
True
So, if you built a class named OrderStates that overloaded the operators like I did here and then listed all states, you'd effectively get an enum with the comparison overloads.
A simple extension method should yield some fairly readable code:
public static class OrderStatesExtensions
{
public static bool Is(this int n, OrderStatesstate)
{
return (States) n == state;
}
public static bool Is(this OrderStates state, int n)
{
return n.Is(state);
}
}
// usage
order.State.Is(OrderStates.Something)
Though, to be fair, I'm not sure how this will work when it's sent to the server; i.e., this may only be useful after the results have been returned.
The approach I have used and it is not mentioned here is that I created partial class of the Order (because EF generates the classes as partials) and then I put a method there which does the cast. You have to do it in every class that uses the enum, or any other enum. However, you have to define those enums by yourself anyway and at least it is quite clean.
public partial class Order
{
public OrderState GetOrderState()
{
return (OrderState)this.OrderState.Id;
}
}
I have a case where I have several sets of numbers (register values). I want to improve readability and also to check appropriate types (only certain values make sense in certain functions).
In my particular implementation, I made them enums - so I have a set of enums now.
Now I seem to have reached the end on this approach, since I want to divide them into sets of valid enums for certain applications - so function A could for example take (a value from) enumA, enumB and enumC as input, but not enumD which is a description of different functionality.
I already looked into enums in interfaces and enum inheritance - both are dead ends, not possible in C#.
I wonder now how the solution to this problem might look like. I would like to get intellisense on the possible values and also have some type safety, so that I could not (well, at least not without maliciously casting it) feed the wrong values in.
How to achieve this?
(Possible solutions would be to simply write several functions taking several different enums - still possible but not really nice, or something like Is there a name for this pattern? (C# compile-time type-safety with "params" args of different types) - both just seems not too nice.)
One option is to scrap enums and use your own clases designed to mimic enums. It will be a bit more work for you to set them up, but once you do it will be easy enough to use, and will be able to have the functionality you've described.
public class Register
{
private int value;
internal Register(int value)
{
this.value = value;
}
public static readonly Register NonSpecialRegister = new Register(0);
public static readonly Register OtherNonSpecialRegister = new Register(1);
public static readonly SpecialRegister SpecialRegister
= SpecialRegister.SpecialRegister;
public static readonly SpecialRegister OtherSpecialRegister
= SpecialRegister.OtherSpecialRegister;
public override int GetHashCode()
{
return value.GetHashCode();
}
public override bool Equals(object obj)
{
Register other = obj as Register;
if (obj == null)
return false;
return other.value == value;
}
}
public class SpecialRegister : Register
{
internal SpecialRegister(int value) : base(value) { }
public static readonly SpecialRegister SpecialRegister = new SpecialRegister(2);
public static readonly SpecialRegister OtherSpecialRegister = new SpecialRegister(3);
}
Given this, you could have a method like:
public static void Foo(Register reg)
{
}
That could take any register, and could be called like:
Foo(Register.NonSpecialRegister);
Foo(Register.OtherSpecialRegister);
Then you could have another method such as:
public static void Bar(SpecialRegister reg)
{
}
Which wouldn't be able to accept a Register.NonSpecialRegister, but could accept a Register.OtherSpecialRegister or SpecialRegister.SpecialRegister.
Sounds like you have exhausted the capabilities of the static type system on the CLR. You can still get runtime validation by wrapping each integer with a class that validates that the value you try to store in it actually is a member of the static set.
If you have a reliable test suite or are willing to do manual testing this will at least catch the bugs instead of the bugs causing silent data corruption.
If you have multiple "sets" that you want to keep apart you can either use class inheritance or have a set of user-defined conversion operators which validate that the conversion is OK at runtime.
I don't know what specific requirements you have but maybe you can use class-based inheritance to check some properties statically. The base class would be the larger set in that case and derived classes would specialize the set of allowed values.
You have basically two options:
Option 1: Multiple enums
Create multiple enums, one for each application, and replicate the values in each enum. Then you can cast between them. For example:
enum App1
{
Data1 = AppAll.Data1,
Data2 = AppAll.Data2,
Data42 = AppAll.Data42,
}
enum App2
{
Data2 = AppAll.Data2,
Data16 = AppAll.Data16,
Data42 = AppAll.Data42,
}
enum AppAll
{
Data1 = 1,
Data2 = 2,
Data16 = 16,
Data42 = 42,
}
App1 value1 = (App1)AppAll.Data2;
App2 value2 = (App2)value1;
This will give you IntelliSense.
Option 2: Determine which are allowed
Create a method that returns a boolean on which values are allowed (this may be virtual and overridden for each application). Then you can throw an exception when the enum value is wrong.
public bool IsAllowed(AppAll value)
{
return value == AppAll.Data2
|| value == AppAll.Data16
|| value == AppAll.Data42;
}
if (!IsAllowed(value))
throw new ArgumentException("Enum value not allowed.");
This will not give you IntelliSense.
A few notes:
You cannot have inheritance for enums because under the covers enums are represented as structs (i.e. value types).
In C# you can literally cast any value to your enum type, even when it is not a member of it. For example, I can do (App1)1337 even when there is no member with value 1337.
If you want compile type checking, you are better off with distinct enums for distinct cases. If you want to have a master enum with all of your possibilities you can write a test that ensures that all of your "child" enum lists are valid subsets of the master (in terms of Int casts).
As an alternative, I would have to wonder (since no code is provided, I can only wonder) if you might not be better served with objects with methods for each enum option. Then you inherit out objects with the various methods instead of enums. (After all, it seems that you are using Enums as proxies for method signatures).
I have a class named "Creature" which is in one of several stages. There are only seven stages, but each stage has a different timespan that will be used throughout the application. I'd like to do something like the following:
enum Stage
{
One,
Two,
Three,
Four,
Five
};
But then also somehow attach a Timespan to each of those, so that
Stage.One.Time
returns something like "one hour". How can this be achieved?
Unfortunately, enums in C# are pretty limited. You have a couple of options though:
Create extension methods which can add whatever logic you want. You could then write:
Stage.One.ToTimeSpan()
(where ToTimeSpan is the extension method, which would probably either use a Dictionary<Stage, TimeSpan> or a switch statement)
Write a "smart" enum which is actually just a type with a limited set of values:
public sealed class Stage
{
public static readonly Stage One = new Stage(TimeSpan.FromHours(1));
public static readonly Stage Two = new Stage(TimeSpan.FromHours(5));
// ...
private readonly TimeSpan time;
public TimeSpan Time { get { return time; } }
private Stage(TimeSpan time)
{
this.time = time;
}
}
The disadvantage of this is that you now can't switch on stages :(
Trying to decipher an appropriate OO design to implement. The basic scenario is that you have a PstnNumber which is essentially a 10 digit phone number that always starts with 0 (e.g. 0195550000). A rule has been introduced to allow auto-correcting of a number if the leading 0 is missing (e.g. 195550000).
START EDIT
I realised the original question may have been misunderstood (thankyou kindly to those whom have answered already), so I have edited to try and better explain the scenario.
END EDIT
I started playing with some preliminary concepts and then thought I would ask if there was a more appropriate way to go or do one of these suffice (on some level)?
Concept 1
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number)
{
this.Number = number;
}
}
public class AutoFormattedPstnNumber : PstnNumber
{
public override string Number
{
get { return base.Number; }
set { base.Number = value.PadLeft(10, '0'); }
}
public AutoFormattedPstnNumber() : base() { }
public AutoFormattedPstnNumber(string number)
{
this.Number = number;
}
}
Concept 2 (removed)
Concept 3
public class PstnNumber
{
public bool AutoCorrect { get; set; }
private string number;
public virtual string Number
{
get { return (this.AutoCorrect) ? this.number.PadLeft(10, '0') : this.number; }
set { this.number = value; }
}
public PstnNumber() : this(false) { }
public PstnNumber(bool autoCorrect)
{
this.AutoCorrect = autoCorrect;
}
public PstnNumber(string number) : this(false)
{
this.Number = number;
}
public PstnNumber(string number, bool autoCorrect) : this(autoCorrect)
{
this.Number = number;
}
}
I think Concept 1 may violate the Liskov Substitution rule because the subclass changes the behaviour of the Number property (happy to learn if I've misunderstood that).
Any alternative suggestions would be received happily.
do you have to do the autoformatting when the object is instantiated? If not,
what about:
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number) { this.Number = number; }
public AutoFormatNumber { get { return Numer.PadLeft(10, '0'); } }
}
avoid getter-setter-surprise
Avoid getters returning a different value than the one accepted by the setter. Imagine the following snippet:
if (input.Value != current.Number)
{
NumberChangedAgain = true;
current.Number = input.Value;
}
A simple solution would be to make PstnNumber immutable:
temp = PstnNumber.FromString(input.Value);
if (temp != current) { ... }
canonical format
If some data has different representations, there is a lot of advantage to storing it in a canonical representation, and move the format conversions to factory functions and getters / formatters. For example, you don't need to test comparison for short vs. long, long vs. short, short vs. short, long vs. long.
different aspects
Do you need the distinction between an "autoformatted" and a "normal" number, or is this merely a question of input and output - i.e.
does display format (short or long) depend on how the number was entered, or on where it is displayed?
is 0195550000 == 195550000 ?
I'd prefer to fold both classes into one if possible (i.e. when "entered with or without 0 can be forgotten"):
public class PstnNumber
{
private string m_number; // always in long format
public static PstnNumber(string s) { ... } // accepts short and long form
public string Number { get { return m_number; } }
public string AutoFormatted { { get { ... } }
}
Otherwise I'd go with Option 3, but always store the long format in m_number.
In Option 1 and Option 2, you aren't preserving the original number anyway, rendering the subclass worthless (except to know that it was autoformatted at some point, which doesn't seem like useful information). The alternative to make these Options more useful would be to format on Get instead of Set.
Option 3 is therefore the preferred pattern out of these three options, but I would also ask - why can't the PstnNumber also simply detect the number of digits, and autoformat accordingly?
If you follow the rules - there is one that says that "each routine (read class) should do only one thing and do it well".
According to that I would make PstnNumber just hold the number, and create some sort of factory that produces the right number.
Doing both in the same class means that you are weaving domain logic and representation. I prefer them separated.
I'd ask why your class name is so cryptic. "Number" is clear to me, and "P" suggests "phone", but what's the "stn" telling me? A few extra keystrokes would make this class more self-documenting.
I'd also ask about the logic of a default constructor that does not initialize the underlying data members to some value. I think a default constructor should have a sensible default value if possible.
I feel like option 1 is overkill. I don't think inheritance is making this model clearer or better. I don't see how it breaks Liskov substitution, which demands that you can use the subclass in any situation that calls for a base class. The methods map 1:1 as far as I can see. How is Liskov violated?
Option 2 says these are two separate classes with no relationship. That doesn't seem right to me.
All this work suggests that your problem will require that you use both classes. You'll have situations where the leading zero is NOT required and others where it is. Is that true? Or are you always going to require the leading zero?
I don't care for any of your options. I'd prefer an interface or a static factory or even modifying the class you have to anything you've suggested. It feels like a mere formatting issue. Do you store the number with the leading zero? If not, maybe it's just a view concern.
Do you have a really strong reason to have a setter and not have your members final? If not, that's probably a bigger problem than any other variation between the three.
So I'd go for a stateless #3 which means making the number final and gettng rid of the autoFormat variable.
For simplicity I'd just have a getNumberRaw and getNumberFormatted
Better yet, you could have getNumberRaw and getNumber(formatType) where formatType actually contains the code that formats the number since the format may change again in the future and combining formatting (view) with your phone number (model) isn't optimal.
(PS/EDIT): just the fact that a phone number can change is NOT a good reason to have a setter! Creating a new phone number object and replacing the old one will almost always work!
I am not familiar with c#, but I'd do this:
public class PstnNumber {
readonly string number;
public PstnNumber(string number) {
this.number = number;
}
public string getNumber() {
return number;
}
static public PstnNumber createNumber(string number) {
return new PstnNumber(number.PadLeft(10, '0'));
}
}
Of course if I knew how Properties work, I'd probably do it differently :)
I would go with a much simpler version, overriding the ToString method, or even, creating an ToString overload that receives the bool parameter indicating that the number should be formatted.