Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I'm working on a Model and am using enum for a list of named items.
class Verse
{
public int Number { get; set; }
public string Text { get; set; }
}
class Chapter
{
public int Number { get; set; }
public List<Verse> Verses { get; set; }
}
class Book
{
public string Name { get; set; }
public List<Chapter> Chapters { get; set; }
}
class Bible
{
public Versions Version { get; set; }
public List<Book> Books { get; set; }
}
enum Versions
{
asv1901,
bbe,
darby,
kjv,
nasb,
niv,
nkjv,
nlt,
rsv,
web,
ylt
}
That seemed like a logical way to do it, but I'm finding that working with enum is adding unnecessary difficulty.
foreach (var chapter in chapters)
{
var bibleitem = new Bible();
bibleitem.Version = (Versions)Enum.Parse(typeof(Versions), chapter.version);
}
Would it make more sense to just use string[] or something? I'm sure there is some added benefit, to enum, but I question my benefit.
The guidance from Microsoft is here:
https://msdn.microsoft.com/en-us/library/ms229058%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
In particular note: Do not use an enumeration for open sets
People write new Bibles all the time, so your set of enumerated values could change. You would be better off using string constants, for instance, where you could add more at will.
While we are at it, some additional critiques of your code.
class Verse
{
public int Number { get; set; }
public string Text { get; set; }
}
Why is this a class, and why are the properties settable? Do you envision having an existing Verse in hand, and wishing to change its number and text to something different? If not, then don't allow it. I would write this as
struct Verse
{
public int Number { get; private set; }
public string Text { get; private set; }
public Verse(int number, string text) : this()
{
this.Number = number;
this.Text = text;
}
}
Once it is created, it does not change. Also, this is a small immutable thing that is logically a value, so make it a struct.
class Chapter
{
public int Number { get; set; }
public List<Verse> Verses { get; set; }
}
Again, if you have an existing chapter, do you intend the set of verses to change? Because anyone can call Add on a list. Also, this constrains you to having the list available at all times, rather than computed lazily from a database. Make this IEnumerable<Verse>.
enum Versions
{
asv1901,
bbe,
This violates both naming guidelines and general legibility. Spell things out! AmericanStandardVersion1901 is far better than asv1901.
You should use enums when you have a named list of constants in your code and you know that this particular list is not gonna change over time (hence called names list of constants).
what benifits do you get?
READABILITY. Using enums increases the readability of your code. Consider the scenario where I have 2 employee types: Permanent and ContractBased. Now I can do this in my code like this:
if employee.Type == 1
// deal with permanent employee
else if employee.Type == 2
// deal with contract based employee here
such code is hard to read and maintain as no one could guess what employee.Type == 1 or what employee.Type == 2 means.
If I define an enum instead like this:
enum EmployeeType { Permanent=1, ContractBased=2 }
my code becomes like this:
if employee.Type == EmployeeType.Permanent
// deal with permanent employee
else if employee.Type == EmployeeType.ContractBased
// deal with contract based employee here
the readability of code gets maximized and also I have intellisense available.
The problem with strings:
1) you would end up having hard-coded string literals in your code
2) no intellisense
3) more memory consumption
how to deal with added complexity?
you should have an enum type variable for chapter.Version (which is right now missing) instead of int. that way you wouldnt need to do the parsing.
but I'm finding that working with enum is adding unnecessary difficulty.
it depends on your needs. if your set will not change enum is the best way to go as it adds a more control with a verbose description and limited set that cannot be bypassed when you work with many developers on the same project.
But
if your set can change during the development of the solution and you can't preview the set than a string would be the better way to go
Enums usually work best when:
No one adds or removes records to it anytime soon (hopefully never).
You don't need to use the real value behind your enum records.
You don't need to use the name of your records.
Enum.Parse can be used to get the enum record from a string, but as you noticed it's pretty ugly and I discourage you from using it. If you have the integral enum value you can simply perform a cast like this:
Versions version = (Versions)0;
But note that an enum is not guranteed to be of type int, it could also be any other integral value. int just happens to be the default. I do however also discourage you from relying on the enum's real integral value because something like this is also possible:
public enum Versions
{
One = 1,
Two = 2,
Three = 3
}
public void Do()
{
Versions version = (Version)-9;
// version is now Versions.One.
// Its value however is -9, what kind of version should -9 be?
}
The code above runs without errors because the runtime doesn't perform any checks on the value you are using for the cast.
The answer to your question depends on the nature of Versions. If you believe it will not be changed in the future then it is a good canditate for an enum in most cases. But you should use the enum everywhere across your application. I see in your sample that you are using the version as a string and therefore need to perform an ugly Enum.Parse. Consistency is an important factor when using enums, well it always is but it doesn't hurt to point it out again.
If you think your records are of a more dynamic nature you are probably best suited with strings. In that case you should use strings consistently. (Just wanted to point it out once again)
using the enum provides methods for comparing instances of this class, converting the value of an instance to its string representation, converting the string representation of a number to an instance of this class, and creating an instance of a specified enumeration and value.
Correcty using im class.
Exp.
public enum Versions
{
asv1901,
bbe,
darby,
kjv,
nasb,
niv,
nkjv,
nlt,
rsv,
web,
ylt
}
Next, implement
foreach (var chapter in chapters)
{
var bibleitem = new Bible();
bibleitem.Version = (Versions) "Your class enum"(typeof(Versions), chapter.version);
}
Enum and more used for good programming practices, clean code
Referency using enum: Enum Class Microsoft
Related
I am working on a program that uses a grid system. The system needs a method that works on every element of the grid, based on the value of its neighbours' elementType. What I currently use is something along the lines of the follows:
enum ElementType{
A,B
}
if (neighbourUp.elemType == ElementType.A && neighbourDown == ElementType.A){
method1();
}
if (neighbourLeft == ElementType.A and current == ElementType.B){
method2();
}
and so on. As you can see this is hard to manage when the types increase. Ideally I would like to use polymorphism here but I feel creating a class for each combination is too much work. Also there may be cases where the method for some combinations is the same.
I would like some advice on how to approach this. Also the ElementType needs to be expandable to accommodate new types that may get added later.
You can use the Strategy Design Pattern which comes under Behavioral Patterns to avoid execution of code base on conditions
You can use these links to know more about strategy design patterns
https://www.dofactory.com/net/strategy-design-pattern
https://www.youtube.com/watch?v=v9ejT8FO-7I
store both of values in array with keys and apply for loop on neighbour and then ElementType, then you can compare using key values until the items in array.
I would define a list of rules and then your main code simply loops around all the cells and then invokes the rules that match for a cell. Then you can add or remove rules relatively easily in the future without changing the main loop logic.
So you need a class that represents a rule, each rule indicates the left/right/up/down types that it matches against and then has a method that is called if the match occurs. Make the matching fields nullable so you can indicate if you do not care what the neighbour type is...
class Rule
{
public ElementType? Left { get; set; }
public ElementType? Right { get; set; }
public ElementType? Top { get; set; }
public ElementType? Bottom { get; set; }
public Action Process { get; set; }
}
...in practice your 'Process' would need at least one parameter, a reference to the cell that is being processed. So you can change it to be Action or whatever.
Consider the following code:
public interface IIdentifiable<T>
{
T Id { get; set; }
}
public interface IViewModel
{
}
public class MyViewModel1 : IViewModel, IIdentifiable<int>
{
public string MyProperty { get; set; }
public int Id { get; set; }
}
public class MyViewModel2 : IViewModel, IIdentifiable<string>
{
public string MyProperty { get; set; }
public string Id { get; set; }
}
I also have class that operates with ViewModels:
public class Loader<T> where T: IViewModel
{
public void LoadData()
{
/*some important stuff here*/
if (typeof(IIdentifiable<??>).IsAssignableFrom(typeof(T)))
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<??>) ds).Id != ((IIdentifiable<??>) d).Id)).ToList();
} // ^---- and there the second ----^
/*some important stuff here too*/
}
}
Now, as you can see, viewmodels that I have might implement the IIdentifiable<> interface. I want to check that, and if it's true,
I want to make sure my data list does not contains any entry that are already present in my _dataSourse list.
So I have 2 questions:
I don't know what IIdentifiable<> has in its generic parentheses, it might be int, string or even GUID.
I tried typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) which is the correct syntax, yet it always returns false.
Is there a way to check whether T is IIdentifiable<> without knowing the exact generic type?
If there is an answer for the first question, I would also like to know how can I compare the Id fields without knowing their type.
I found this answer quite useful, yet it doesn't cover my
specific case.
I know that I probably can solve that problem if I make my Loader<T> class a generic for two types Loader<T,K>, where K would be the
type in IIdentifiable<>, yet I would like to know if there are other solutions.
P.S. In addition to my first question: I'm also curious why one can write something like this typeof(IIdentifiable<>).IsAssignableFrom(typeof(T)) if it returns false when the generic type of IIdentifiable<> is not specified?
Edit: I guess, in hindsight, I understand why I can't write the code this bluntly - because there's might be the collection ICollection<IViewModel> where the entries implement different types of IIdentifiable<> (or don't implement it at all), and the check like that would fail awkwardly. Yet maybe there is a way to do something like that with some restrictions, but without creating second generic parameter to my Loader?
Try add two methods to your Loader<T>:
public bool CanCast<TId>()
{
var identifiableT = typeof(IIdentifiable<>).MakeGenericType(typeof(TId));
return identifiableT.IsAssignableFrom(typeof(T));
}
public IEnumerable<IIdentifiable<TId>> Filter<TId>(IEnumerable<T> data)
{
return data.Where(d => _dataSource.All(
ds => !((IIdentifiable<TId>) ds).Id.Equals(((IIdentifiable<TId>) d).Id)));
}
Then in LoadData
if (CanCast<int>())
data = Filter<int>(data);
else if (CanCast<Guid>())
data = Filter<Guid>(data);
// and so om
Well, I would suggest you to always use a string for identification. You can convert int and guid to a string. And if you want to ensure proper type is used then you can prefix the string with type information.
However, I do think that the performance of you algorithm would be very poor as you wouls essentially loop 2 containers so it would be O(n * m).
Thus it would be best to either do appropriate SQL query if both sources are from the database or use a dictionary if you do it in code. Alternatively if data is properly sorted, you could find duplicates more efficiently.
By the way generics are quite limited in C#. Sometime using ˋFunc<>ˋ could help but even then you have to provide extra information to the algorithm.
We should address your question in two steps (because there really are two problems to solve here).
First, make following change to your interface IIdentifiable<T>
public interface IIdentifiable<T>
where T : IEquatable<T>
{
T Id { get; set; }
}
This will ensure that you can compare Id properties correctly.
Secondly, in your LoadData() method, change the if statement to
if (T is IIdentifiable<T>)
{ // ^- here's the first problem
data = data.Where(d => _dataSource.All(ds => ((IIdentifiable<T) ds).Id != ((IIdentifiable<T) d).Id)).ToList();
}
This question already has answers here:
Should I use public properties and private fields or public fields for data?
(13 answers)
Closed 7 years ago.
Just want to make sure.
public class Product
{
private decimal unitPrice;
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
//private string code;
public decimal Unitprice
{
get
{
return unitPrice;
}
set
{
if (value >=0)
unitPrice = value;
}
}
}
Why we would have to make private variable to unitPrice to return the value to UnitPrice, does it written for some reasons ?
You dont make it private just to return the value for it. private is one of the access modifier here. They are used to limit the scope of the access/usage of that particular variable in your code.
private here means that unitPrice is currently accessible or can be used by this particular class only. No other outside assembly can use this variable.
If you want to access a variable outside in other areas, you can opt to make it public.
Hope this clears it.
From design perspective the unit price property is exactly the same as the other properties but because there is a constraint on it.
if (value >=0)
only positive prices are valid, you have no other option than to foresee a private variable whereon the property is based.
In earlier versions of .NET we could not do something like this :
public int Id { get; set; }
And had to write it out in full all the time. The notation above is more handy and it makes the code clearer too. It used to be like this :
private int _id;
public int Id{
get{ return _id;}
set{ _id = value;}
}
Yes, get and set properties are useful when you want to have some control over variable. Consider the following case.
If you specify the variable as private you want no one to be able to access your variable.
But if you want others to be able to access your private variable but you dont want others to change it. In this case you can use Properties
public class Product
{
private decimal price;
public decimal Price{get{ return price;}}
}
now others have access to the price but they cant change it
In your case you are allowing others both to get and set your unitprice, which is equal to giving unitprice public access. However you are allowing on one condition that the unitprice should be set to 0. So C# properties are perfect match for this scenario.
Hope this helps!!
The public property UnitPrice is exposed to other classes to be read or modified. But being a property allows your class a degree of control over the value - you can validate any change for instance. Also, internally you can completely change how the value is obtained and modified without changing the contract of the class. So in other words, you would be able to make such changes without affect any consumers.
The backing field unitPrice is purely an implementation detail, it is internal state that is encapsulated by the class. Exposing this field means you lose any and all chance to modify the derivation of the value and you have no entry point for validating changes to the value. Properties may seem pointless abstraction at first but they will help make your code more maintainable as changes can be more easily confined to single classes.
The get and set blocks are purely syntactic sugar and under the covers the compiler creates two methods called get_UnitPrice() and set_UnitPrice(x) that are used for read/write operations on the property. You could just use similar methods but properties are more readable and designed to be a low cost way of interacting with class state and methods are for providing behaviour.
I got a need for two extacly idential enums with diffrent names
I can do
enum DoorStatus{Open,Closed,Locked,Broken};
enum WindowStatus{Open,Closed,Locked,Broken};
and will probably be bit easier to read.
but Id rather not to duplicate code
in C++ id do
typedef Door,Window;
what is the soultion in C#?
and why have both you ask?
I got Application That Handles a Window
application that handles a Door.
I want the Window application devoloper send me data using 'WindowStatus' enum
the 'Door' guy use 'DoorStatus' enum.
I believe that user should know or care I got other devices that can be abstracted similarly.
EDIT: used
enum HatchStatus{Open,Closed,Locked,Broken};
using DoorStatus = HatchStatus;
using WndowStatus = HatchStatus;
EDIT2:
Error A using clause must precede all other elements defined in the namespace except extern alias declarations
:(
If you just want an alias, you can use a using directive:
using Enum2 = Enum1;
I suppose the question is if you have two different enums that have the exact same values - then why keep both at all?
The best solution is to pick one and refactor everything to use just one.
Update
Now that you've updated your example, I think you should consider whether an enum is actually the best solution.
public class ObjectState
{
public int ID { get; set; }
public string Description { get; set; }
}//should really be immutable
//should also implement IEquatable<ObjectState> for equality
public static readonly State_Open = new ObjectState()
{ ID = 1, Description = "Open" }
public static readonly State_Closed = new ObjectState()
{ ID = 2, Description = "Closed" }
public static class DoorStatus
{
public static readonly ObjectState Open = State_Open;
public static readonly ObjectState Closed = State_Closed;
}
//and WindowStatus if you want.
public class Door {
public ObjectState State { get; set; }
} //or perhaps refactor to a shared base/interface StatefulObject
Now you can simply do:
new Door() { State = DoorStatus.Open; }
If you also implement IEquatable<ObjectState> then you can compare the equality of two object's state as well; you'd then likely implement GetHashCode as well meaning you can also use a state as a key in a grouping or dictionary.
The good thing now is that both an open window and an open door now have exactly the same state that equate directly, rather than using some syntactic sugar to get around a design that required identical enums.
Final Update
Since the above is 'horribly complex' - despite being, I think, good design; the best you can do is ensure that two separate enums at least share the same underlying values for identical states:
public enum States
{
Open
}
public enum DoorStates
{
Open = States.Open
}
public enum WindowStates
{
Open = States.Open
}
Ultimately if you're using an enum you cannot get around the need to have two separately defined ones - this solution simply means that Open is equal for any object that can be in an Open state.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
This might sound a little stupid but I am still curious about what the community thinks.
So I have a WebService returning a UpdateInfo class.
Now consider the following definitions
public enum TTCFileType
{
API = 0,
BOOKMARK,
TICKMARK
}
public class FileUpdateInfo
{
public string FileName;
public string FileDownLoadURI;
public TTCFileType FileType;
}
public class UpdateInfo
{
public FileUpdateInfo fuInfo;
//Other
}
Here is the issue, if the TTCFileType has the value TICKMARK then I need another enum viz Tickmark Type( the biz logic demands this information). I am wondering what is the best way to represent that. I dont want a method signature where I have something Like
UpdateMethod( UpdateInfo ui, TickMarkType tt)
where I examine tt if ui.fuInfo.FileType == TTCFileType.TICKMARK
I guess I am trying to find an semi elegant way at least to represent the conditional requirement for getting the second piece of information out ( in many ways this so reminds of VARIANTS , if var.VT == VT_[thingy] then use vt.[thingy] and yes I know how c# developers feel about unions :-)
Anyway curious if there is a nifty way to do this
Thanks
Just include TickMarkType field to FileUpdateInfo class?
I'd be tempted to go with something like:
public enum TTCFileType
{
API = 0,
BOOKMARK,
TICKMARK_TYPE1 = 100,
TICKMARK_TYPE2 = 101,
TICKMARK_TYPE3 = 102
}
and so on. Depending on how many there are and how manageable it would feel within the wider context of your code.
Ideally, you need two additional structure(s)
public enum TickmarkType
{
TYPE1=0,
TYPE2
}
public class TickMarkFileUpdateInfo : FileUpdateInfo
{
public TickmarkType type;
}
And then read about polymorphism in web services
Store the enum value as an int. Add some offset to the value for your second enum (e.g., 1000) so that if the value is from the first enum it's 0..2 and if it's from the second enum it's 1000.1010 or whatever. Then you can set 2 properties, one that returns a nullable TTCFileType and the other that returns a nullable TickType, to read and write the values into the int field.
It seems like you're trying to use only data structures, when using OO features (such as inheritance) might help you. Maybe this example code gives you some ideas:
public class Update
{
// ... ?
}
public class FileUpdate : Update
{
public virtual string Name { get; set; }
public virtual string DownloadUri { get; set; }
public virtual bool IsTickMarked { get; set; }
}
public class ApiFileUpdate : FileUpdate
{
// ...
}
public class BookmarkFileUpdate : FileUpdate
{
// ...
}
You can still serialize these, given the proper serialization attributes.
In fact, you can define (potentially virtual) methods on these various classes, and actually use them to implement your program.
Overly segregating your data and code is known as the Anemic Domain Model Anti-Pattern.