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.
Related
As a very simplified and stupid example of what I'm dealing with, suppose I had the following class with a simple static int property:
public class MyClass
{
public static int MyVar { get; set; }
}
So, if I wanted to set that property via code, it would be easy enough with something such as:
MyClass.MyVar = 2;
But, how could I take care of (again, to simplify the example) passing in a string and have it converted to an int?
The only way I could think of doing it is to create a helper method such as:
public class MyClass
{
public static int MyVar { get; private set; }
public static void SetMyVar(string sMyVar)
{
MyVar = int.Parse(sMyVar);
}
}
And then in code run:
MyClass.SetMyVar("2");
I would love to know if there was a better way to accomplish this than having to add in that extra method.
Although you definitely shouldn't do this because it's confusing to read, you could create the property this way
class MyClass
{
private static int _property = 0;
public static object Property
{
get
{
return _property;
}
set
{
_property = Convert.ToInt32(value);
}
}
}
You would have to cast this to an int whenever you wanted to use it as an integer but this is best I could think of.
is this what you were trying to do?
class newclass
{
private static int MyVarValue = 0;
public static int MyVar
{
get;
set
{
MyVarValue = Convert.ToInt32(value);
}
}
}
This would not compile because the value that a property gets set to has to be of the same type as the property itself. But if you are taking a list of objects in a constructor and assigning them to the properties, there you can do something like this...
class newclass
{
private static int MyVarValue = 0;
public newclass(List<object> startingList)
{
MyVarValue = Convert.ToInt32(startingList[0]);
}
}
You can use the compiler's method overload resolution to pick a SetMyValue method depending on the type of the argument. Inside each SetMyValue method you have a mechanism to convert all of the different input values to the same underlying type.
Doing this is probably a bad idea - but here goes anyway. It doesn't have quite the semantics that you're asking for but it's close:
//A class with multiple 'set' methods that will silently handle
//type conversions
class MyClass{
private int myValue;
public int MyValue { { get return this.myValue; } }
public void SetMyValue(int value){
this.myValue = value;
}
public void SetMyValue(string value){
this.myValue = Convert.ToInt32(value);
}
}
In statically typed languages, switching types silently in a way that loses information is not a very wise idea. There are other, dynamically typed languages that let you play fast and loose with types but C# is not one of them. You have to go out of your way in C# to get dynamic typing.
Doing this is probably a pain in the butt from a maintenance standpoint. I would put some more thought into the underlying problem that you're trying to solve that lead to this question.
I am working on ASP.NET MVC 4 application even though for this exact problem I think it's irrelevant. I am using EF 5 with Code First and I have entity Menu where a menu can be one of four different types. In my entity the type of the menu is declared as
public class Menu
{
//other properties
public int Type { get; set; }
}
and I have declared the different types as constants:
public static class MenuType
{
public const int Report = 10;
public const int Contract = 20;
public const int Taxes = 30;
public const int Interests = 40;
}
So if I want to get all Menus from Contract type I have this:
unitOfWork.MenuRepository.GetAll().Where(x => x.Type == MenuType.Contract).ToList();
even though it's working OK I want to change this with enum values, I've tried this:
public static class MenuType
{
public static enum Types
{
Report = 10,
Contract = 20,
Taxes = 30,
Interests = 40
}
}
But then to retrieve the same records from above my code is:
unitOfWork.MenuRepository.GetAll().Where(x => x.Type == (int)(MenuType.Types.Contract)).ToList();
a lot more unreadable and more to write as well. I've seen enums to be used in a way similar to the way I use the constants. I'm not sure, maybe I have to implement additional method.
However how I can change the constants with enum values without making the queries more unreadable? Maybe some additional method like MenuTypeValue("Contract")...
You would have to change the type of the property on the Menu class to match the new enum you declared
public class Menu
{
//other properties
public Types Type { get; set; }
}
This way you will be comparing an enum to an enum and your code will become nice and clear again.
If you cannot do that, you will be probably better off with sticking to int constants or you will need to cast between int and the enum type all the time.
Change type of property "Type" in your model to enum. EF5 smart enough to internally convert it to int.
Take a look here: http://msdn.microsoft.com/en-us/data/hh859576.aspx
If what you're trying to do is make it more readable, why not move the logic into the repository class.
So you could make a call:
unitOfWork.MenuRepository.GetAll(MenuType.Type.Contract);
Then in your repository just have a method such as:
List<...> GetAll(MenuType.Type type = null) { ... }
So now you can still call GetAll without the type as it's an optional param but in that method you can work out what you need to be returning. Your calls will look cleaner then.
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 :(
I've been looking around, and so far haven't managed to find a good way to do this. It's a common problem, I'm sure.
Suppose I have the following:
class SomeClass : IComparable
{
private int myVal;
public int MyVal
{
get { return myVal; }
set { myVal = value; }
}
public int CompareTo(object other) { /* implementation here */ }
}
class SortedCollection<T>
{
private T[] data;
public T Top { get { return data[0]; } }
/* rest of implementation here */
}
The idea being, I'm going to implement a binary heap, and rather than only support Insert() and DeleteMin() operations, I want to support "peeking" at the highest (or lowest, as the case may be) priority value on the stack. Never did like Heisenberg, and that whole "you can't look at things without changing them" Uncertainty Principle. Rubbish!
The problem, clearly, is that the above provides no means to prevent calling code from modifying MyVal (assuming SortedCollection) via the Top property, which operation has the distinct possibility of putting my heap in the wrong order. Is there any way to prevent modifications from being applied to the internal elements of the heap via the Top property? Or do I just use the code with a warning: "Only stable if you don't modify any instances between the time they're inserted and dequeue'd. YMMV."
To answer your question: No, there's no way to implement the kind of behavior you want - as long as T is of reference type (and possibly even with some value-types)
You can't really do much about it. As long as you provide a getter, calling code can modify the internal contents of your data depending on the accessibility of said data (i.e. on properties, fields, and methods).
class SomeClass : IComparable
{
private int myVal;
public int MyVal
{
get { return myVal; }
set { myVal = value; }
}
public int CompareTo(object other) { /* implementation here */ }
}
class SortedCollection<T>
{
private T[] data;
public T Top { get { return data[0]; } }
/* rest of implementation here */
}
//..
// calling code
SortedCollection<SomeClass> col;
col.Top.MyVal = 500; // you can't really prevent this
NOTE What I mean is you can't really prevent it in the case of classes that you don't control. In the example, like others have stated you can make MyVal's set private or omit it; but since SortedColleciton is a generic class, you can't do anything about other people's structures..
You can have a readonly property (that is, a property with only a getter):
private int myVal;
public int MyVal { get { return myVal; } }
But be careful: this may not always work how you expect. Consider:
private List<int> myVals;
public List<int> MyVals { get { return myVals; } }
In this case, you can't change which List the class uses, but you can still call that List's .Add(), .Remove(), etc methods.
Your properties don't have to have the same accessibility for get/set. This covers you for anything that returns a value type (typically structs that only contain value types) or immutable reference types.
public int MyVal
{
get { return myVal; }
private set { myVal = value; }
}
For mutable reference types, you have other options, such as returning Clone()s or using ReadOnlyCollection<T> to keep the caller from changing them:
private List<int> data;
public IList<int> Data
{
get { return new ReadOnlyCollection<int>(this.data); }
}
Only implement getters for your properties and modify the collection by having add/remove methods
I understand your problem now. I think this should work:
class SortedCollection<T> where T: ICloneable
{
private T[] data;
public T Top
{
get
{
T ret = (T)data[0].Clone();
return ret;
}
}
/* rest of implementation here */
}
The ICloneable constraint ensures that the type parameter implements the ICloneable interface. (if this is acceptable)
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.