I'm practicing C# and have only been learning for about a month. I have a question that maybe is a bit on the beginner side so I hope someone doesn't mind answering for me.
I have a class called yourCharacter. In this class sits all the information for someone's character. I want to give the user the ability to create a new character so I've created a method/function to do so. My question is, can I place a function within yourCharacter that creates a List of yourCharacter. Is this doable? Is it bad form to do it this way? Should I be creating this list in my Main class and then calling a function within the main class to do this?
I hope my question is clear enough, please let me know if you need further detail. The only reason I want to do this is because in my head it makes more sense to group my methods/functions with the class it is manipulating and or working with.
class yourCharacter{
//insert a bunch of variables here
public static void newChar(){
List newCharacter = new List<yourCharacter>();
}
}
What you have there is doable for sure.
A class can contain itself as a member. This might make sense in some scenario, but think about yours and see whether it applies. In your case it seems as if you're trying to have a mechanism to group characters - but it's not a good way to do it. Why? Read on...
Say you had a box. This box contained another box inside... that box could contain another box inside...
So in that case, if I made a class which represents this kind of box it might make sense to add that class into itself.
Making a class like that represents a system in reality where a box contains other boxes.
What system are you trying to abstract, so that it is useful that a character contains other characters?
I can think of something: let's imagine a character in your game can swallow other characters and they'll live inside his tummy...
If you want to group them - you'd likely want to use another class which represents the system under which your characters are grouped like this:
Say your game has an adventure party! The adventure party can invite other people to join and they go questing together. Let's say this adventure party has a leader which decides who can join and who can't. You still probably wouldn't make a character which contains other characters... you would rather create a class called "AdventureGroup" with a list of "ordinary" party members and a leader, you would assign a string which represents the "group nickname", and all other kinds of things which represent the group as an entity. Something like that... you get the jist.
Related
I'm trying to save some oxyplots into a list where I can then later generate a pdf or png file for printing to a printer. Is this something that is possible?
I have two classes; one is a plotUsercontrol and the other being a Baseplot.
Also, I did not implement the oxyplots feature of the app so I'm not fully aware of the differences between PlotModel and PlotView.
In my snippet PlotUserControl. I have the following function which I created to grab all the plots from the BasePlot. I declared it as void because I was not sure what type to declare the Data type for the list and function as.
public void getPlots()
{
foreach(var plot in plots)
{
Console.WriteLine(" ");
Console.WriteLine(plot.getImage());
}
}
Bellow is just a fucntion from my baseplot that gets the PlotModel. Also I wasn't sure whether to return the plotModel or the plotView.
public PlotModel getImage()
{
return this.plotModel;
}
I hope this make sense. New to c#.
Do you want to safe your images or the plots into a list? If you want to save plots into a list, that's already done (plots).
However if you want to save images into a list that's a bit different but very easy. I suggest you take a look at List<T>. I can supply you with method that will do all the work but it is so easy that i think you can manage to set up the list on your own.
Here is a quick rundown tho: List<T> will create a list which allows you to save objects of the datatype T inside of it. T is a so-called generic type which means you can hand it every data type that can be instantiated.
Hint: T would be PlotModel in your example.
If you need any more help, feel free to contact me but I think you can manage creating said list on your own.
This is the link to the Microsoft Docs of List<T>, but imo they are not the best docs for beginners. Just look for some tutorials on Google.
Another tip tho, rename your functions. In C# first letters of words in method names are uppercase (e.g: GetPlots(), GetImage()). This is just a common naming style although you can stick to lowercase.
This is for c#
I'm an old dinosaur, writing 360 assembler since the 70's, trying to write stuff for the PC. Along the way I am replacing my old write it myself thinking with use the existing infrastructure.
Here is what I have now. Two objects, System and Planet. A field in System has a pointer to the next System, there is also a second chain of Systems that meet current selection criteria. Also System has a pointer to Planet and Planet has a pointer to the next Planet. Planet also has a chain of all planets.
Now the questions. Should I use lists and have C# handle all the linking etc. I'm fairly sure 1 object instance can be in multiple lists, so I can have 1 list of all systems and a second list of selected systems. Plus have a list of Planets in the system and another list of all Planets.
I also want to save this mess to disk. I've spent some time looking at serialization and it appears to be great at saving all the instances in a list, but things break down when you want to serialize multiple classes. Am I missing something basic, just a yes will send me back to looking, or do I have to roll my own?
I don't want code examples, just a gentle puch in the direction I should be looking at.
I would simply create two classes, one being the System with a List<Planet> containing all its planets and the other one being the Planet, containing a reference to his system (if one is required). The systems are themselves saved in a List<System>. Like the planets they could hold a reference to their parent so they have access to the list, but if they don't need to, its fine.
Saving this stuff should be three lines of code with a serializing system of your choice, either in text or binary (Json.Net, the Xml stuff .Net provides, yaml, binary formatter...).
Linked lists are not worth the implementation, they aren't as useful as dynamic arrays (like the List<T> in System.Collections.Generic or the Vector<T> in C++) which resize themselves when needed, and they aren't that easy to keep track of. They definetly have applications but this is not one of them IMO.
Should I use linked list or list...
The answer depends on what your object represents and how you are going to use it. For example, if I was representing houses, and the people who live at each house; then I might choose to have a collection of House objects. I'm using collection as a generic term there: specifically, I would probably use List<T> from the System.Collections.Generic namespace (where T can represent any type, so it would be a List<House> in this case), unless I needed something more specific like a Stack<T>, Queue<T>, Dictionary<T,U>, etc, etc.
Notice how in this approach, each House doesn't know which house is next, because the whole concept of 'next' relates to the collection of houses: each individual house doesn't need to know where it is in the collection - that's the responsibility of the collection. This is a design principle called "separation of concerns".
For example, if I wanted to create a different collection of House objects (e.g. the ones with red front doors), I could do so by creating a new collection, referring to the same House objects; whereas with the approach mentioned of an object having a reference to the next one, I would have to create a different House object because the next value would be different in those two collections.
Using List<T> allows you to focus on writing your classes, instead of having to write the implementation of the collection.
There are also performance reasons against using linked lists unless you only plan to access the data in sequential order.
Each House has-a collection of people. So I might put a property on House called People, of type List<Person>. And if I needed to get to the house that the person was associated with, I could have a property on Person called House, of type House.
I hope this structure of Houses and People corresponds to your scenario with Systems and Planets.
Maybe also worth looking at When should I use a List vs a LinkedList
...and how do I serialize it.
Plenty on the internet, try these...
How to Serialize List<T>?
https://www.thomaslevesque.com/2009/06/12/c-parentchild-relationship-and-xml-serialization/
Hope this helps to get you started.
From the sound of it, I will create class of System, Planet with one to many reference of planets in System (List here). In order to avoid strong coupling between System and Planet, One can look at Chain of Responsibility pattern.
Saving this data to database one can serialise using Json.Net (newtonsoft). SQL server supports directly putting json array.
Pseudo code:
class Planet {
public Planet(System system) {System = system;}
public System System {get; private set;} // singleton
}
class System {
public Planet Planet {get; set;}
// list of planets
private List<Planet> planets = new List<Planet>();
public List<Planet> Planets { get {return planets; } }
}
I have a (not quite valid) CSV file that contains rows of multiple types. Any record could be one of about 6 different types and each type has a different number of properties. The first part of any row contains the timestamp and the type of record, followed by a standard CSV of the data.
Example
1456057920 PERSON, Ted Danson, 123 Fake Street, 555-123-3214, blah
1476195120 PLACE, Detroit, Michigan, 12345
1440581532 THING, Bucket, Has holes, Not a good bucket
And to make matters more complex, I need to be able to do different things with the records depending on certain criteria. So a PERSON type can be automatically inserted into a DB without user input, but a THING type would be displayed on screen for the user to review and approve before adding to DB and continuing the parse, etc.
Normally, I would use a library like CsvHelper to map the records to a type, but in this case since the types could be different, and the first part uses a space instead of comma, I dont know how to do that with a standard CSV library. So currently how I am doing it each loop is:
String split based off comma.
Split the first array item by the space.
Use a switch statement to determine the type and create the object.
Put that object into a List of type object.
Get confused as to where to go now because i now have a list of various types and will have to use yet another switch or if to determine the next parts.
I don't really know for sure if I will actually need that List but I have a feeling the user will want the ability to manually flip through records in the file.
By this point, this is starting to make for very long, confusing code, and my gut feeling tells me there has to be a cleaner way to do this. I thought maybe using Type.GetType(string) would help simplify the code some, but this seems like it might be terribly inefficient in a loop with 10k+ records and might make things even more confusing. I then thought maybe making some interfaces might help, but I'm not the greatest at using interfaces in this context and I seem to end up in about this same situation.
So what would be a more manageable way to parse this file? Are there any C# parsing libraries out there that would be able to handle something like this?
You can implement an IRecord interface that has a Timestamp property and a Process method (perhaps others as well).
Then, implement concrete types for each type of record.
Use a switch statement to determine the type and create and populate the correct concrete type.
Place each object in a List
After that you can do whatever you need. Some examples:
Loop through each item and call Process() to handle it.
Use linq .OfType<{concrete type}> to segment the list. (Warning with 10k
records, this would be slow since it would traverse the entire list for each concrete type.)
Use an overridden ToString method to give a single text representation of the IRecord
If using WPF, you can define a datatype template for each concrete type, bind an ItemsControl derivative to a collection of IRecords and your "detail" display (e.g. ListItem or separate ContentControl) will automagically display the item using the correct DataTemplate
Continuing in my comment - well that depends. What u described is actually pretty good for starters, u can of course expand it to a series of factories one for each object type - so that you move from explicit switch into searching for first factory that can parse a line. Might prove useful if u are looking to adding more object types in the future - you just add then another factory for new kind of object. Up to you if these objects should share a common interface. Interface is used generally to define a a behavior, so it doesn't seem so. Maybe you should rather just a Dictionary? You need to ask urself if you actually need strongly typed objects here? Maybe what you need is a simple class with ObjectType property and Dictionary of properties with some helper methods for easy typed properties access like GetBool, GetInt or generic Get?
I have posted a question on here previously asking similar advise, but this project has evolved significantly, so I would like to ask for advice on how the experts would tackle this problem.
First, I will describe what the problem is, then how I have currently looked at it. Please, I want to learn - so do critise my approach/tell me what I can/should do better!
Requirements:
I have a log file decoder. I have three different systems generating log files. Each system is slightly different. There are seven different types of log files. Each log file can be in either ASCII format (human readable) or binary format (not human readable). So there are a lot of different logs - but many are similar. For example, for most, the binary and ascii is the same info in a different form.
There is also one log type which is in a totally different structure, i.e., if a, b and c are different values - each stored 6 times, most logs are type 1. One log is type 2.
type 1: abcabcabcabcabcabc
type 2: aaaaaabbbbbbcccccc
On top of this, each system has a status register. The three systems are all different in this respect. i.e. 7 * 8 bit registers, 3 * 32 bit registers... These need processing after the log is decoded (for the logs that contain the info) and then a chart needs to be plotted for other info (where required).
So, my solution so far:
I have a LogFile struct. This contains a DataTable to contain all the data. Also contains a few strings, such as serial numbers which are read from the log files and some Enums (log type, system type, encoding format)
I have a Parser class. This has some static methods : to Identify what logs are contained within a log file (An ASCII file can contain several different ones - the GUI will find out what is in there, ask the user which one they want and then decode it. Another static method to act as a factory and give back an instantiation of the Parser class - there are 3 types. One generic. One for binary of the (type 2, above) and one for ascii of the (type 2, above).
I have a SystemType class. This contains info such as status register meanings, log structures for each type. I.e. when decoding a type, the GUI will call the 'GetTable, which will give back a DataTable with columns of the fields to read from the file. The Parser can then just cycle through the columns, which will allow it to know what type of variable to read from the file (Int, Single, String, etc).
I have a Reader class. This is abstract and has two child classes - one for ascii, one for binary. So, I can call reader.ReadInt and it will handle appropriately.
There is also a class to generate charts and decode the status register. Status registers are just an array of array of strings, giving name and description of each bit. Perhaps this could be a struct - but does it make a difference? There is also a further class which analyses 3 values in one particular log and if they are present, will insert a column with a value calculated from them (they are strings).
The whole things just isn't very flexible, but I didn't want to write a different class for each of (3*7*2 =) 42 log types! They are too similar, yet different so I think that they would have resulted in a lot of duplicate code. This is why I came up with the idea of the DataTable and a generic Parser.
So, sorry for the long text!
I have a few other questions - I have used a DataTable for the data because I use a DataGridView in the GUI to display all of this to the user. I assumed this would simplify this, but is there a better way of doing this? When I bind the DataTable to the DataGridView, I have to go through each one looking for a particular row to highlight, adding tooltips and setting various column widths, which actually takes as long as the whole decoding process. So if there is a more efficient way of doing this, it would be great!
Thanks for any feedback!! Please, I can not have too much advice here as I have been playing around, rearranging for ages trying to get it in a way that I think is a nice solution, but it always seems clunky and very tightly coupled, espcially with the GUI.
You probably want a class instead of a struct.
I wouldn't use a DataTable unless I had to. I would instead use a List or something similar, you can still bind this to your DataGridView. For formatting the grid, if this is an option, buy a UI control library that will give you more options than the DataGridView does. My favorite is Telerik, but there are a bunch of them. If that isn't an option, then you'll have some custom UI logic (either JavaScript or row binding code behind) that will look at the record your binding and make decisions based on the properties of the class.
As far as the 42 different classes, all with similar code, create an abstract base class with the reusable code, and derive from this class in your different logtype classes, overriding the base functionality where needed.
Use interfaces to separate functionality that must be implemented by the logtype, and implement those interfaces. That way when you are iterating through a list of these classes, you know what functionality will be implemented based interface.
It sounds like you would greatly benefit from using interfaces to separate contract from implementation, and code to the contract to decouple your classes.
Hope this helps.
The only thing that pops out at me is this
I have a LogFile struct
Are you actually getting a benefit from it being a struct that outway the potential pitfalls?
From the guidelines
CONSIDER defining a struct instead of a class if instances of the type
are small and commonly short-lived or
are commonly embedded in other
objects.
DO NOT define a struct unless the type has all of the following
characteristics:
It logically represents a single value, similar to primitive types
(int, double, etc.).
It has an instance size under 16 bytes.
It is immutable.
It will not have to be boxed frequently.
I'm currently having a problem with a ShoppingCart for my customer.
He wants to be able to add Text between the CartItems so I was wondering if there is some way to still only have one List.
My solution would be to have two lists, one of type IList that gets iterated over when calculating Weight and overall Price of the Cart while having another IList that only exposes the necessary fields for displaying it in the ListView and that is a SuperType of CartItem. (But how do I then access additional fields for the listView, defaulting weight and price to 0 in the Description-Text-Class would break LSP).
But having two lists somehow feels a bit odd (and still gives me problems), so I was wondering if I could do some sort of a TypedList where I specify the Type of each item.
Any suggestions are welcome, I'm not really happy with both options.
Use an interface:
ICartListItem
And make your list be:
List<ICartListItem>
Now, create several types, have all of them implement this interface, and you can store them all safely in your list.
Alternatively, if you want there to be some default logic in a CartItem, use a base class instead of an interface.
You can make a class and, inside of that, define the properties of the required list type and then make a list of same class.
For example, if I wanted to make a list of strings and bools, I would make two properties in one class and then make a list of that class.
The Interface sounds like overkill. I'd just add a property to your current CartItem named something like "TextAfterItem".
Also: make sure your customer understands the cost of this feature in terms of security overhead. It sounds like they think this should be a simple update, but you're allowing users to enter text that will be displayed directly back to the page, and that's a dangerous proposition.