Use List<>, Array or something else? - c#

i'm doing some programming exercises from Exercism.io and need some input on how to start on the Grade-School assignment.
The assignment is to add name and grade and receive name from grade index in the form of List<string>.
The first tests for the assignments looks like this:
[Test]
public void New_school_has_an_empty_roster()
{
Assert.That(school.Roster, Has.Count.EqualTo(0));
}
[Test]
public void Adding_a_student_adds_them_to_the_roster_for_the_given_grade()
{
school.Add("Aimee", 2);
var expected = new List<string> { "Aimee" };
Assert.That(school.Roster[2], Is.EqualTo(expected));
}
I'm not looking for a complete solution but i need some advice on what Roster should be. My thought was that Roster would be a array of List like this:
public List<string>[] Roster = new List<string>[];
The problem with this is that it doesn't pass the first test because i have to assign a length for the array so count will never be 0.
I need a push in the right direction on how to solve this.

I would not use an Array of Lists, that would get confiusing. Read into Object Oriented Programming (OOP) and look at the user of Classes.
I would have a class to represent a Person (or in your case a student) somthing like:
public class Student
{
public string Name {get; set;}
public string Grade {get; set; }
}
and store them in a simple List of Students
public List<Student> Roster;
Another way to look at is a Dictionary so,
public Dictionary<string, string> Roster;
where each entry is Student name and Grade so:
Roster.Add("John Mclain", "A*");
You could also look into Enumerations (Enums) to store the grades instead of using Strings.

If grade is your index then you should use a Dictionary<int, List<string>> structure. The int is the key, in your case grade and the list contains the names of students with that grade.
When you add a grade and student, you check if the dictionary has any value for that grade, if so, then get the value (of type List<string>) and add the student name to that list, otherwise create a new list and add the student name.

Your list initialisation is wrong, thats why you get error that you have to assign a size for the array.
This is how you make a list:
public List<string> Roster = new List<string>();
But the better way in this case is to create a class Student or use a Dictionary.

Related

Declare list field and the constructor in a user defined class in C#

So i am learning C# using the "Murach's C# 2015" textbook. In chapter 13 page 411, there is a this code:
public class ProductList
{
private List<Product> products;
public ProductList()
{
products = new List<Product>();
}
So the first line "public class ProductList" declares a class
The second line "private List products;" declares a class variable (ie: "Field")... which in this case is a list... I don't understand this? All I have learned so far is that a list is initialized like this:
private List<Product> products = new List<Product>();
Can anyone explain this to me? Is this just how it is always done for a list? Or is this short hand? Are there other ways to go about it?
I understand that the next part of the code is a constructor, that is:
public ProductList()
{
products = new List<Product>();
}
And I see the "new" key word here that I am used to seeing for a list.
private List<Product> products;
This declares the field. I.e. tells the compiler that the class contains a field of this type. It will be assigned the default value for the type (i.e. null in this case) unless something more is done.
private List<Product> products = new List<Product>();
This is a combined declaration and initialization. It does same as the above, but also assignes the field with a newly constructed object. In your case the examples are equivalent. But consider
public ProductList(int capacity)
{
products = new List<Product>(capacity);
}
Here we must split declaration and initialization since we need some parameter for the initalization.

How do I Create an instance of a class, and access its methods and variables, using user input for its name?

I want to be able to create and reference a class using input from the user. I'm new to coding, so I'm not quite sure the best way to go around this. If there is a better way of doing this without classes, I am open to suggestions.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("What is the name of the Salesmen?");
string userInput = Console.ReadLine();
//Create Class Instance
Salesmen[userInput] = new Salesmen();
//Access Class Methods or Variables
[userInput].Age = 35;
}
}
class Salesmen
{
public int Age;
public int Salary;
}
Instances of classes are created with thenew keyword, and class members and functions are accessed with a period . (usually read as"dot").
Salesmen salesman = new Salesmen();
salesman.name = userInput;
The first line creates a new Salesmen object (or an instance thereof) and the second sets its name field to whatever the value of userInput is.
Since you haven't declared a field to hold that value, however, we'll need to modify your class so that it can store the name (I've also made the field names lowercase --that's the convention):
class Salesmen
{
public int age;
public int salary;
public string name;
}
It's not clear from your question, but judging from the name you chose for the class, it would seem that you're looking to store more than one salesman object. In that case you'll need a data structure like an array, or a list. We'll rename your class to Salesman (singular), since every object will represent a single salesman and declare a list to hold all salespeople:
List<Salesman> salespeople = new List<Salesman>();
Salesman s = new Salesman();
s.name = userInput;
salespeople.Add(s);
First - the square brackets you're using, are for indexers, so it's not applicable at this point.
Second - to instantiate an object, you need to use a constructor, like this:
Salesmen salesman = new Salesmen();
Where "salesman" (note case) is now the name of your new object. You can then access that object's members like this:
salesman.Name = userInput;
You'll have to add the 'Name' property to your Salesman class, for it to have a name.
There are other ways to achieve this, but I think this will get you started.
Get familiar with the concept of classes and objects, in the long run it'll improve your code. Happy coding!

what is name of the List<T> design pattern called? how to implement it

As we know that the List for C# is possible to put the function behind but do the function to filter the list.
For example,
Assume that the many count inside the students List.
var students=new List<student>();
Then to get the list of student we can add some function behind like
students.find(id).sortbydesending(k=>k.x).skip(10).take(5).toList();
the sequence of putting the skip() and take() will effect the result.
I was doing the coding on an method to retrieve the list of student accordingly.
First,
I want to do something similar with the list function.
For example i need order the list Of Student According student name.
instead of doing
students.sortbydescending(k=>k.name).toList();
I want code is like
students.sortbyNamedesc().toList();
and it will return the same result as above.
Second is the design pattern name and (If possible) implementation guide
This is because I plan to do something like this.
getStudent().searchName(searchQuery).sortby(id);
Then i can get student name similar with search query and sort it by the student id instead of
getstudent(searchQuery,id,skip,take);
public IList<Student> getStudent(searchQuery,id,skip,take){
var students=new List<student>();
if(searchquery!="")
students.where(x=>x.x==searchquery);
if(skip!=null&&skip!=0)
students.skip(skip);
if(take!=null&&take!=0)
students.take(take);
return students;
}
These are called extension methods. You define them as static methods in static classes, with a this before the first parameter. For example:
public static class StudentExtensions
{
public static IEnumerable<Student> OrderByNameDescending(this IEnumerable<Student> source)
{
return source.OrderByDescending(x => x.Name);
}
}
Usage:
studentList.OrderByNameDescending()
(The static class must be accessible at the point of usage and you must be in its namespace, or include it with a using statement.)

C# Class Arrays stored in an Array

New to multidimensional arrays and a bit stuck on a little project I am working on.
Getting a error when I try to store 2 arrays (student and teacher) in to a course array, when creating them as class arrays
Below is the code from my main()
Student stud1 = new Student("Alex", "Kelly", DateTime.Parse("14/07/2000"));
Student stud2 = new Student("Tom", "Smith", DateTime.Parse("16/08/198
Student stud3 = new Student("Mary", "Jones", DateTime.Parse("10/01/1998"));
//add students to an array and get the count
Student[] studentArray = new Student[3] { stud1, stud2, stud3 };
int count1 = studentArray.Length;
//add teacher objects
Teacher prof1 = new Teacher("Beckham");
Teacher prof2 = new Teacher("Pele");
Teacher prof3 = new Teacher("Maradonna");
Teacher[] teacherArray = new Teacher[3] { prof1, prof2, prof3 };
//course Object
Course course1 = new Course("Programming with C#");
Course[,] courseList = new Course[,] { {studentArray} , { teacherArray } };
I am getting the error on the last line shown, when I try to add the { studentArray, teacherArray } to the courseList array.
The error is
cannot implicitly convert type Student[] to Course
If I change the array from Course to object [,] it works fine
Do I need to add something to my class file?
It looks like you code can be refactored.
For example, why don't your Course class look like:
class Course
{
public string Name;
public List<Student> Students;
public List<Teacher> Teachers;
}
It is more natural and object-orianted way. In this case you don't need two-dimensional array, and you can use only List<Course>.
Also note - in many cases List<T> is more convinient then T[] array sincу it is resizing automatically.
The error you are experiencing is because Course array will only allow objects of Course type. You cannot place other objects or arrays with it.
To resolve your problem, it might be better to have the Student and Teacher arrays as a properties of the Course object. These can then be assigned values as needed.
See:
https://msdn.microsoft.com/en-us/library/9b9dty7d.aspx for information on arrays.
https://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx for information on properties.
Update following edit
The object[,] array will work because object is the base type for all other types. As a result of this, an object[] can have any other type assigned to it. As you indicate you are learning to program so it might be worth reading up on object oriented design - It will help you model your data better. For a starting point try https://msdn.microsoft.com/en-us/library/dd460654.aspx.
What you should try to do is use OBJECT ARRAYS . This array will store the the different objects and it will also retain their form .
Check out this link . Its quite detailed on this topic.
enter link description here
To extend on a previous answers, always think about how you separate up your data. For example, the Course itself is a very 'static' concept compared to the attendees and the tutors. The Course could even have different dates with different attendees etc but will not change whereas dates and those involved will.
So your model could be:
public class CourseSchedule
{
public CourseSchedule(Course course, Student[] students, Teacher[] teacher)
{
this.Course = course;
....
}
// Some sort of Date too
public Course Course { get; private set; }
public IEnumerable<Student> Students { get; private set; }
public IEnumerable<Teacher> Teachers { get; private set; }
}
Multi-dimensional arrays are worth understanding but are specific to certain types of programming - graphics, mathematical transforms etc. You tend to use them for low level coding but for modelling real world structures such as your course booking they are generally not appropriate.

Can I get an element from a List<T> by string-based indexing in .Net? (I.E.: T val = List<T>["NameHere"])

In C#/.Net, I know that with a DataSet you can access a named table by DataSet.Tables[NameHere].
Is it possible to do this with a List (if the elements in the list have a property by which you can find them like that?)
I'm not talking about List<T>.Find(tVar => tVar.Prop == "NameHere"),
I want to just be able to say T val = List<T>["NameHere"].
Is that possible, and if so, how would I go about accomplishing this?
Also, as a kind of aside, I'm sure this has a proper name : What is it?
It is called "indexer", read more from here
You can create your own class which implement IList interface and add indexer to it.
Create a KeyedCollection<TKey,TValue> for your type:
public class SomeClass
{
public string Name { get; set; }
public string Value { get; set; }
}
public class SomeClassCollection : KeyedCollection<string,SomeClass>
{
protected override string GetKeyForItem(SomeClass item)
{
return item.Name;
}
}
[TestClass]
public class KeyedCollectionTests
{
[TestMethod]
public void Test()
{
var items = new SomeClassCollection
{
new SomeClass{Name = "Name 1", Value = "Value 1"},
new SomeClass{Name = "Name 2", Value = "Value 2"}
};
items["Name 1"].Value.Should().Be("Value 1");
items[1].Value.Should().Be("Value 2");
}
}
#Will You will add additional complication to your code base by rolling your own apart from any performance impact. I reckon your problem can be solved by utilising existing functions in .Net
There are 2 ways to solve your problem
Using List to point to your set of objects to allow you to index by int AND
Using a Dictionary to point to the same set of objects to allow you to index my string. An object can be reference by more than one collection
Using a DataTable with an Int column and a string column, put an index on each column and use the Find function. (Not sure if you could add an index on each columns like a db table as I haven't use DataTable for a long time but I'm sure you can look up MSDN documentation)

Categories

Resources