I would like to create sample program.
It will has Department Class,Position Class,Employee Class.
Each department will has any positions. I don't know that how I should specify that.
And I don't use DataBase. It is only to learn OOP in Console.
Whether to use an Enum or a Collection mainly depends on the following criteria:
How often you expect the available values of positions to change?
Who will conduct the changes?
Does the Position only have an Id and a Text or do you expect it to have other data fields as well.
Will each position be available once per Department and not several times?
If your answers are
Seldom.
The developer.
Only Id and Text.
Yes
then an Enum with a FlagsAttribute is a good option. However, if there is any doubt about this, creating a class for a Position and adding a collection is a better way as it is more flexible. It also allows you to add the same kind of position several times to a Department, if this is a requirement.
Though you don't use a database up to now, also note that adding an Enum property to the Department is much easier to save in comparison to have related positions that should go into a separate structure.
Based upon your comment, I suggest to add a constructor to set the relevant data in a department upon creation (you might also think about whether the data should be private fields as you could not access them from the outside):
class Department
{
public Department(Dep departmentType, IEnumerable<Position> positions, int employeeCount)
{
this.departmentType = departmentType;
this.positions = new List<Position>(positions);
this.employeeCount = employeeCount;
}
Dep departmentType;
List<Position> positions;
int employeecount;
}
You could then create a new Department like this:
var dep = new Department(Dep.Electric,
new Position() [] { new Position(), new Position() },
5);
Please note that you might also need to add a constructor to your Position class. In the above sample, I create two Position objects that are added to the Positions list in the Department.
If position is going to be just string values, its best to have them as enum and write your logic around it.
If new position gets added to the enum, the logic will break and it would help you to write specific functionality for each position.
You can write a class around this position enum to alter its functionality based on the enum.
Related
I am attempting to add multiple flags of similar types (arrows) to a live chart using a C# windows forms project. This is to provide a label when a value falls out of a pre-defined specification.
I am currently stuck in how to create new instances of the ArrowAnnotation class so if multiple events happen there will be multiple flags for the people checking the chart. I am able to create one instance and manipulate the position to the latest data point in the series (it shouldn't be a stretch to lock it to a historical point, I just haven't done that yet.)
I have an understanding of creating multiple instances of other classes and keeping track of them with lists/ dictionaries but this one has me stumped (or maybe I don't have as good an understanding as I think?)
I can't share the code I have directly but I think I can write some example code if needed.
edit-
I am looking into using a memberwise clone to copy common attributes of each arrow and add those objects to a dictionary.
Thanks
Okay, I have managed to figure out how to do this for my use case.
When updating the live chart I can call a method if a parameter falls out of specification. In that method I create a new instance of the annotation, and the properties that I want to use as a template. (these values can also be changed with conditional logic if you want slight variation, and can be passed in with the argument) than add that newly made annotation to the annotation group. I am still looking for improvements to the code. I am still wanting a way to assign a name to the arrow, than recall that one and modify it (if I wanted to). And change the pass/fail criteria than apply annotations for the new failure points (but that is going into new territory)
// This is not the full method just the part that counts for this question.
private ArrowAnnotation floatArrow;
private void UpdateChart()
{
GenerateArrows(dateTime, sensorValue);
this.chart1.Annotations.Add(floatArrow);enter code here
}
private void GenerateArrows(DateTime x, double y)
{
floatArrow = new ArrowAnnotation();
floatArrow.Name = Convert.ToString(x);
floatArrow.ToolTip = Convert.ToString(x);
floatArrow.AxisXName = "ChartArea1\\rX";
floatArrow.AxisYName = "ChartArea1\\rY";
floatArrow.X = x.ToOADate();
floatArrow.Y = y;
floatArrow.Height = 5;
floatArrow.Width = 0;
floatArrow.BackColor = Color.Red;
}
This problem is a bit hard to expose via the title so I hope the following clarifies my intentions a bit.
Suppose you have the following data classes:
class abstract Employee {
string ID;
}
class FullTimeEmployee : Employee {
string schedule;
}
class PartTimeEmployee : Employee{
string schedulePartTime;
}
class WheelsSpecialist : Employee{ }
class InteriorsSpecialist : Employee{ }
class Workshop {
WheelsSpecialist wheely_guy;
InteriorsSpecialist interiors_guy;
}
Now, suppose that I instantiate my workshop as follows:
var Workshop = new Workshop{
wheely_guy = new PartTimeEmployee(),
interiors_guy = new FullTimeEmployee();
}
Please assume that the structure / inheritance and instantiations here provided are immutable.
What I'd like is to generate an ID set on Employee.ID that survives the runtime and is consist and independent from class properties / developer implementation.
Understand also that: The path of each object property in the workshop instantiation is guaranteed to be UNIQUE.
As so, a good ID for the WheelsSpecialist in Workshop.wheely_guy would be "Workshop.wheely_guy". (for example) because no path will ever be the same when I'm instantiating the workshop.
When I access the object "Workshop.wheely_guy.ID" I'd like to have "Workshop.wheely_guy" there or something analogous.
I imagine something like this would work (non valid C#, logic intact):
class PartTimeEmployee {
//instantiationPath is for example, "Workshop.wheely_guy"
onCreate(string instantiationPath){
this.ID = instantionPath;
}
}
I've tried this with StackTrace and whatnot, but couldn't find a way of doing it right.
Whether this instantiationPath method is used or not, the solution requires that:
I get to keep my structure as is in the example EXCEPT for properties. Those can change.
When I want to add a new dimension to my workshop variable I CAN'T, as a developer, be responsible for awarding a class it's own unique property.
As so, doing something like "this.ID = wheels" manually is not an option (also, depending this ID on properties that the developer must implement is also not viable).
Can this be done some way that meets my demands?
Thank you!
The provided code does not compile, and the object design/inheritance used seems a bit off. You probably want to work on the abstractions themselves. But that is not what you asked (mainly). It's kind of hard to figure out what exactly you asked, but I will do my best to answer what I think you asked (mostly):
"I want a field of an object instance to contain an automatically calculated navigation path by which it is accessible in some collection or composite object unrelated to the object itself" -> while close to impossible in C#, this might be entirely/easily possible in other languages. Still, the concept itself seems a little off.
The premise here is that the Employee object does not and should not know about the Workshop object Think about part-time employees trying to work separate shifts in separate workshops at the same time, and other possible changes in the business logic regarding Employees and Workshops.
Let's walk through some of the possibilities, ordered by viability:
Doing some magic at constructor/instantiation time in the abstract constructor code (Stack Frame walking, callerMember tricks, Reflection?, AST parsing?)
At instantiation, in a constructor, the stack trace does not contain information about which property/field it is about to be assigned to (if at all for that matter, it might just need to be instantiated, not assigned to anything). So there is no way to set such an id at constructor time.
Doing some magic in the Id property getter
There is no way to pass in parameters to a property getter, so we run into the same type of problem as with option 1: the stack trace contains no useful information by the time the getter is accessed.
Make the Employee object know about Workshop
No, just no.
Some weird runtime/weaving magic to "calculate" these paths when they are accessed?
Maybe, but how much effort to put in and to what purpose?
Expression parsing in a separate method:
//Left out the non-compiling code.
public static void Main(string[] args)
{
var Workshop = new Workshop
{
WheelsGuy = new PartTimeEmployee(),
InteriorsGuy = new FullTimeEmployee()
};
Console.WriteLine(GetObjectAccessPath((_) => Workshop.WheelsGuy));
}
public static string GetObjectAccessPath(Expression<Func<Workshop, Employee>> member)
{
string body = member.Body.Reduce().ToString();
// the line below might take some tweaking depending on your needs
return body.Substring(body.IndexOf($"{nameof(Workshop)}"));
}
// Output: Workshop.WheelsGuy
Use Reflection in a separate method to "get" a list of properties that are of any type derived from Employee and based on that Generate a list of ids with something like properties.Select(p => $"Workshop_{p.Name}");
Most viable: Re-design the object model:
(This is my opinion, and the requirements of your project might be different. Even if I am speculating here, the same principles presented here would apply in many other ways).
Extract more abstractions, like Position, Role, and Schedule. Part-time would be a schedule. Wheels guy would be a role. Position would be "an employee that fulfills the role of wheels guy at a workshop." There might be more examples (pay by hour/week/month, tax exemption, etc.).
As a rule, holding too many concerns in one class is a code smell and will get you in trouble quick. You can choose to carve up the classes however you want, but for what you "seem" to want, this part is important: have a class that represents the relationship between employee and workshop.
For example, instead of the Workshop holding instances of Employees: the Position class would hold/know about an Employee, his Role, his Schedule, and the Workshop he works at. The Position's Id could then easily be Id => $"Workshop_{Role}"; or Id => $"{WorkShop}_{Role}", etc. As a bonus, you get the design bonus of the Workshop being free from knowing which types of employees it might hold.
In general, I'd suggest you look into SOLID principles, it's an eye opener.
I'm sorry in advance for the mess you're about to read, because I'm not 100% sure what I'm searching for.
I have created an entire UI system that automatically grabs a list of properties from various scripts/components on GameObjects (Unity) and creates a fitting UI input variant for them (for example, float gets a single line, Vector3 gets 3 lines, color gets something else etc.).
What goes into UI input fields creation is a Component (that we want to look into), while individual created UI inputs store this Component and Property Name. So when input changes in one of input fields, it does SetValue on Property of a Component. Now I have also created a variant where we peak into a Class of a property and basically list Property's Properties, so the UI input stores Component, Property Name, and subProperty's Name and modifies properties as such. All this works well.
So, now I hit a brick wall with Lists. I would like to treat individual elements of a list as properties so that I could pass them into my preexisting UI scheme.
tl;dr Does List<> treat it's individual elements as Properties, Fields or does it depend on the situation? How do I get these properties, fields or their respective names from this list in order to use them with my mess of an UI system? 0 work for me means treating individual elements of List as properties.
----------------------------
EDIT----------------------------
Again I am sorry for this mess of a question. It is a mixture of confused theory and description of an existing situation that I am trying to shoehorn into my already existing project (which is a bit too over the place to be easily reduced to an example).
If anyone grasped what I was asking for, the single easiest solution was to create a property which prior to listing was equated to an element of a list.
Example looks something like this:
public List<MyCustomClass> myCustomList;
[Listable("ForEdit")]
public myCustomClass myCustomPropertyForEdit
{
get;
set;
}
And before withdrawing properties of myCustomPropertyForEdit's class (myCustomClass) I would simply do:
myCustomPropertyForEdit = myCustomList[0]; //or whatever index is in question
Then later on I would do reflection on "myCustomPropertyForEdit" instead of myCustomList. I highly doubt this will ever help anyone because it touches more onto how I built methods for listing properties into my UI, but there it is just in case.
List stores references to objects, by providing an index you get a standard object reference, which you can proceed to query using reflection (do not do it against the list itself as you will get methods of the List class, and notthing related to what the list contains)
take for example:
public Class Tree
{
public int branches;
public Tree(int branch)
{
branches=branch;
}
}
List<Tree> trees = new List<Tree>();
trees.Add(new Tree(3));
now my list has one element at index 0;
so i can do trees[0].branches;
to access the fields/props of an element in trees.
list is not an array, it holds the actual item, allowing you to reference, not just the object but also its own unique variables. as long as they are public in the class.
I am lately starting a project and I have a question.
Let's say I am dealing with a class Person, and a person can have one(or more) deseases he is encountering.
so I have created an enum :
public enum diseases{headache,throat,bruise,gunshot,none}; // enum containing all the diseases
public diseases disease;
And further in code I set a certain disease to that person and it works fine.
Thing is, there might be a point in my project where a person might have 2 diseases.
So there are my questions:
Is using enum the best option here? I want my code to be organized and understood and that's a main reason for using enums.
If using enum is a good option, I have managed to combine this enum with bit-flags(using [System.Flags]) so when time comes I can check for a disease that contains two different values from the enum. is this a good approach?
If using enum is a good option, should I just create a second property from diseases (just like I created disease) and save all the trouble from using bit-flags?
Thanks in advance for any light on that matter, couldn't figure what was the best approach here.
A good option would to make a List<diseases> to hold for a single person.
public class Person
{
public string Name { get; set; }
public List<diseases> Diseases { get; set; }
public Person(string name)
{
this.Name = name;
Diseases = new List<diseases>();
}
}
This way you can enumerate over all the values relatively easily without having to worry about flags.
For example:
var bob = new Person("bob");
bob.Diseases.Add(diseases.gunshot);
var hasHeadache = bob.Diseases.Any(x => x == diseases.headache);
An enum is a plausible (yet a bit simplistic) way to represent one disease.
If someone may have N diseases, then just use a container of objects of that type, such as a list. But you need to choose the right container. A list of diseases may be, for example: { headache, throat, headache, throat, gunshot }. Lists allow duplicates. Whay you may actually need is a set of diseases. A set is a structure which does not allow duplicates.
The choice of how you represent one disease and the fact that a person may have N diseases, so that you need a person to have a container of diseases, are two totally independent facts.
Use the FlagsAttribute on your enum.
[Flags]
Public enum diseases
{
// your values here
}
This should give you what you need.
There is a lot of opinion being asked for here and the right answer is that it depends on a lot of variables what solution is right in any given situation. You CAN use an ENUM to represent multiple values so long as the [Flags] attribute is given to the ENUM. Keep in mind that if you decide to go that route then you are responsible for assigning the values of the ENUM specific non-overlapping values like 1, 2, 4, 8, 16, 32, etc.
Is using enum the best option here? - This depends on how many diseases you would like to cover. If the number is small (10..20) and the list is flat (no hierarchy of diseases) then you are fine. Otherwise, consider some alternative.
is [System.Flags] a good approach? - Yes, in case of a small, flat, list [System.Flags] approach is very good and extremely efficient.
Should I just create a second property from diseases and save all the trouble from using bit-flags? Having a second property in place of running a collection is a terrible idea. If you have to do something twice, chances are, you'd do it N times. Make a collection or bit fields, never go for a second property unless the system is inherently limited to two items (say, a binary tree).
If the list of diseases is not "flat" (e.g. you plan to have ViralThroat, BacterialThroat, and ThroatInjury in place of a simple throat that you have now) you would be better off modeling diseases as classes, and creating a collection of diseases attached to a Person. You could add methods for checking the collection for particular diseases, which could be smart about the search: for example, find any kind of throat sub-disease when a throat is passed as a search criterion.
enum is just one of many perfectly acceptable options here. Others include OO solutions such as base/derived classes, or simple lists of string (or event lists of enums, why not?!). Often the simplest approach is best. We would have to know a lot more about your problem to recommend one over the other.
While using Flags is one solution, I would not recommend it in this case. Flags are not verbose on what they are for. Any time I used flags, I would have to re-learn how to properly work with flags when I needed to modify my code. One simple alternative is creating a property for each possible disease...
public class Diseases
{
public bool Headache {get;set;}
...
public bool HasAnyDisease() { return Headache || Throat || ...;}
}
But that has it's downsides as well. It's not easily extensible. I would recommend using the Decorator Pattern. Each disease could decorate the class which may make future interactions with it easier to maintain. If you need to have variance disease combinations cause different outcomes, this may be better in the long run.
I have a problem which I cant seem to find answer to through searches (either that or I am searching for the completely wrong thing!). I have a list of items called "Top 10" in a sortedlist item that is populated from my DB (SortedList where int is position and string is item). I want to be able to move items up & down the list order at the click of a button and then save the new order back to the DB. I am OK with the DB part it is just the re-ordering I am really struggling with - is a sortedlist the correct collection for this?
Many thanks for any advice offered.
A SortedList is for maintaining order within your SortedList as you add or remove items from it.
You should create a custom list of your objects and then sort on property of that object.
So if your entry in your database was like this you could place it in an object, add it to a list and then sort it using Lambda on which ever criteria you like
public class LeaguePosition
{
public int Position { get; set; }
public string Team { get; set; }
}
List<LeaguePosition> League = new List<LeaguePosition>();
League.Add(new LeaguePosition() { Position = 2, Team = "Wolves" });
League.Add(new LeaguePosition() { Position = 3, Team = "Spurs" });
League.Add(new LeaguePosition() { Position = 1, Team = "Villa" });
League.Sort((teamA, teamB) => teamA.Position.CompareTo(teamB.Position));
You can also then use RemoveAt() and Insert() to move items about to custom positions within the list.
LeaguePosition teamToMove = League[1];
League.RemoveAt(1);
League.Insert(2, teamToMove);
No, a SortedList will keep things in sorted (alpha/numeric) order. You want a plain list that will let you pull things out and insert them at different positions.
A SortedList is going to force each item to keep track of its position within the list relative to the other items (your int position). This should be a responsiblity of the Collection, so you should use some sort of Collection that will allow you to move things up/down/around without having to manually correct each item.
I would say a SortedList is exactly what you want. When you get data back from the database you want to keep it in order based on the position field (what I can tell from your OP). I'm assuming you will have a class that contains the data you're getting back from the DB. To keep the data in the right order you will need to implement the IComparable interface in your custom class so that the SortedList knows what values to use to keep the list in order. This way as you add/remove items you will keep them in the right order.
You could use a generic List<> but then you have to write all the code to sort your items yourself, the SortedList already does this so why re-invent the wheel?
Take a look at this page for more info:
http://www.dotnetspider.com/resources/4679-Applying-custom-sort-SortedList.aspx