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.
Related
This question already has answers here:
Creating a copy of an object in C# [duplicate]
(4 answers)
Closed 3 years ago.
So I have a list:
List<Class> myList = new List<Class>
I create an object that is equal to one of the items so that I can update it:
Class item = myList[0]
I also have a copy of the item (so that I can restore any changes if needed):
Class copyItem = myList[0]
When I update the item the item in myList also updates, which is what I want.
But I don't want this to happen with the copyItem, how do I make it so that the copy doesn't reference the myList?
I think the main issue here is one of expectations:
Class item = myList[0]
does not create an object (assuming that Class is a class, i.e. a reference-type); it makes a copy of the reference and assigns it to the local variable item, but: the reference points to the same, single object.
The key here is that there is only one object; you have only copied the reference, and that's just (essentially) a pointer. It doesn't matter which reference/pointer you use: any change you make still impacts the same object, and you won't have a backup.
For what you need, you'd need to look into creating a clone (deep clone or shallow clone, depending on your needs) of the object.
Alternatively, note that the problems you describe don't apply to value types, but they have much more complex usage constraints that (unless treated very carefully) will trip you up in other subtle ways.
If your Class class (which, by the way, is a terrible name for a class) is simple enough, you can write a copy constructor to help you create a new copy of the instance.
public class Person
{
public Person() { }
public Person(Person person) { Name = person.Name; City = person.City; }
public string Name { get; set; }
public string City { get; set; }
}
In your main:
var people = new List<Person>
{
new Person() { Name = "Jane", City = "London" },
new Person() { Name = "Mike", City = "NY" }
};
var item = people[0];
var copy = new Person(people[0]);
item.City = "LA";
Now;
item.City = "LA"
But
copy.City = "London"
Obviously this approach may not be suitable if your class has a ton of properties or a complex nested structure.
In such a situation you'll need to think about deep/shallow cloning, and this is a good read.
It doesn't really reference myList, only a member of myList. You will probably need to implement Clone() for Class.
You can do something like this below so that you can create new object.
Class copyItem = new Class()
Now assign properties from myList[0] like below
copyItem.propery1 = myList[0].property1
copyItem.propery2 = myList[0].property2
Please see Marc Gravell answer for more explanation.
I'd like to use indexers more, but I'm not sure when to use them. All I've found online are examples that use classes like MyClass and IndexerClass.
What about in a school system where there are Students and Teachers, and each Teacher has a list of Students that they're in charge of - any need for indexers in that scenario? For simplicity's sake: each Student can only belong to one Teacher.
Indexer is a highly specialized property which allows instances of a class (or struct) to be indexed just like an array (properties can be static but indexers cannot).
Why to use indexers:
instead of a new data structure, the class itself is a data structure.
simplified syntax - syntactic sugar
When to use:
if your class needs list(/array) of its instances (example 1)
if your class represents list(/array) of values directly related to your class (example 2)
Example 1:
public class Person{
public string Name{get; set;}
private Person[] _backingStore;
public Person this[int index]
{
get{
return _backingStore[index];
}
set{
_backingStore[index] = value;
}
}
}
Person p = new Person();
p[0] = new Person(){Name = "Hassan"};
p[1] = new Person(){Name = "John Skeet"};
Example 2:
class TempratureRecord{
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 56.5F, 56.9F, 58.8F, 61.3F};
public int Length{
get { return temps.Length; }
}
public float this[int index]
{
get{
return temps[index];
}
set{
temps[index] = value;
}
}
}
Heres a video i have created http://www.youtube.com/watch?v=HdtEQqu0yOY and below is a detailed explanation about the same.
Indexers helps to access contained collection with in a class using a simplified interface. It’s a syntactic sugar.
For instance lets say you have a customer class with addresses collection inside it. Now let’s say we would like to like fetch the addresses collection by “Pincode” and “PhoneNumber”. So the logical step would be that you would go and create two overloaded functions one which fetches by using “PhoneNumber” and the other by “PinCode”. You can see in the below code we have two functions defined.
Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");
If you use indexer you can simplify the above code with something as shown in the below code.
Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];
Cheers.
You typically use an indexer if the class represents a list, collection or array of objects. In your case, you could provide an indexer to provide index-based access to a teacher's students.
An indexer use in your situation would be a TeachersClass class, which would encapsulate the students (collection) and the current teacher. Although you could do the same thing by exposing the list of students, but it does show you an example.
Here is a code example:
public class TeachersClass
{
private List<Student> _students;
public TeachersClass(Teacher currentTeacher, List<Student> students)
{
CurrentTeacher = currentTeacher;
_students = students;
}
public Teacher CurrentTeacher { get; set; }
public Student this[int studentID]
{
get
{
return (from s in _students
where s.Id = studentID
select s).First();
}
}
}
Random order access
You would use an enumerator if your data is normally accessed sequentially.
An indexer on the other hand is useful for directly accessing a specific element, no specific order.
This of course assumes you know the index of the element you want. Comboboxes for example have always supported two values: the string shown to the user, and the id that belongs with it. You could use the id from a selected item in a combobox to directly access the index of your collection, instead of having to search the collection.
The nice thing about indexers in C# is that you can overload them, so you can access items through different kind of keys.
The simple answer (as stated above) is when the class represents/contains a collection of items, the indexer will return the elements of the collection.
public Student this[int index] { ..
In a more advanced case you can create a default behavior with a class and make it look a bit like a delegate, especially when the class represents a mapping, or a process. For example a class that calculates the cooling rate of a beer in the refrigerator:
Instead of typing
temperature = coorsLight.CalculateFutureTemperature(time);
you can condence this to
temperature = coorsLight[time];
if the expected behavior (and intent) of the class is to return a value.
An indexer is a means to select an element from an aggregate such as an array or collection. While I agree in part with Ian Davis, I think indexers represent something more than public API polish.
Indexers are the primary means of accessing arrays and most of the major classes representing collections in the .NET BCL implemented indexers, presumably to provide a common expernce when dealing with types that aggregate other types.
Because indexers are a standard part of the interface to many of the BCLs collection types, and because these types are heavily used, as developers learn .NET as a platform, it is reasonable to suggest that an expectation is created that collections can be accessed using some type of indexer.
If your type's interface matches the expectations that developers have already, then that type becomes easier to use because the developer doesn't have to think. This is true whether the developers in question are internal to your organization or out there in the wild.
Of course there are situations where having an indexer just doesn't make sense, and if thats the case then don't implement an indexer.
Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
Indexers enable objects to be indexed in a similar manner to arrays.
// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}
Code project
I remember there was this time when I had a long inside a class, and some digits of that particular long meant something (for example if the third digit was a 3 it meant that the chart had a specific type of encoding, horrible system I know but I didn't invent it)
So I did something like this to return the xth digit of the number:
protected int this[int index]
{
get
{
int tempN = Number;
if (index > 0)
{
tempN /= index * 10;
}
return tempN % 10;
}
}
It was protected because a different method used it, so it was kind of a helper. Of course a simple GetDigit(int a) would've been the same thing (and more self-explanatory) but at the time I thought it was one of the few times I thought using an indexer would make sense. Haven't used them since =(.
IMHO, Indexers are probably best if you're trying to spruce up a packaged API - it's not worth the effort for your run of the mill business object.
And if you're making some specialized collection, I'd categorize that as sprucing up your packaged API - even if you keep it all in one module.
I am trying to create a basic (very, very basic) inventory system in Unity though C#, and am having trouble deciding how to use arrays. Would it be best to have a different multidimensional array for each inventory slot, with each dimension carrying the integer values of item data? Or use a jagged array , with each "jag" representing a different value of item data? Or is there a better solution that doesn't use arrays? I plan to have around 40-50 inventory slots, and each item having around 10-15 aspects, so neither option seems simple. Any help would be appreciated. Thanks in advance!
The more you divide up the objects are the better. You should normalize the objects as much as possible, being said separate a chair object to multiple parts and have chair inherit / instantiate some generalized properties. I believe the following would explain better;
class Item
{
public string Name { get; set; }
public int Quantity { get; set; }
public Properties Props { get; set; }
}
class Properties
{
public int Weight { get; set; }
public int Height { get; set; }
// All of the possible properties here...
}
The Item has a field called Props which is global for a lot of objects / items in your game, and Item is an object that can refer to many things. If you construct your objects like this, you can use them over and over again instead of creating separate objects for each feature in your game.
Then you can finally create the inventory as the following;
var Inventory = new List < Item > {
new Item {
Name = "Bullet", Quantity = 100, Props = new Properties {
Height = 10, Weight = 10
}
}
};
Edit:
Upon your request, I will try to explain the code a bit more. Lists are generic classes that holds data for you. You could create an array as well but Lists are more dynamic, and you may eventually have sizing issues with Arrays more than with lists. Please check https://msdn.microsoft.com/en-us/library/6sh2ey19%28v=vs.110%29.aspx for more information on Lists.
I believe the second part is the one you may be having a tough time with. The following pseudo code should explain it better.
Class Item { Fields, Properties }
Class Properties { Fields }
new Inventory = List of <Items> ( New Item Class(es))
As you see above, we create List of Items and the Inventory type would be List as well since it would host items.
I hope it makes better sense now.
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.
I'd like to use indexers more, but I'm not sure when to use them. All I've found online are examples that use classes like MyClass and IndexerClass.
What about in a school system where there are Students and Teachers, and each Teacher has a list of Students that they're in charge of - any need for indexers in that scenario? For simplicity's sake: each Student can only belong to one Teacher.
Indexer is a highly specialized property which allows instances of a class (or struct) to be indexed just like an array (properties can be static but indexers cannot).
Why to use indexers:
instead of a new data structure, the class itself is a data structure.
simplified syntax - syntactic sugar
When to use:
if your class needs list(/array) of its instances (example 1)
if your class represents list(/array) of values directly related to your class (example 2)
Example 1:
public class Person{
public string Name{get; set;}
private Person[] _backingStore;
public Person this[int index]
{
get{
return _backingStore[index];
}
set{
_backingStore[index] = value;
}
}
}
Person p = new Person();
p[0] = new Person(){Name = "Hassan"};
p[1] = new Person(){Name = "John Skeet"};
Example 2:
class TempratureRecord{
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 56.5F, 56.9F, 58.8F, 61.3F};
public int Length{
get { return temps.Length; }
}
public float this[int index]
{
get{
return temps[index];
}
set{
temps[index] = value;
}
}
}
Heres a video i have created http://www.youtube.com/watch?v=HdtEQqu0yOY and below is a detailed explanation about the same.
Indexers helps to access contained collection with in a class using a simplified interface. It’s a syntactic sugar.
For instance lets say you have a customer class with addresses collection inside it. Now let’s say we would like to like fetch the addresses collection by “Pincode” and “PhoneNumber”. So the logical step would be that you would go and create two overloaded functions one which fetches by using “PhoneNumber” and the other by “PinCode”. You can see in the below code we have two functions defined.
Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");
If you use indexer you can simplify the above code with something as shown in the below code.
Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];
Cheers.
You typically use an indexer if the class represents a list, collection or array of objects. In your case, you could provide an indexer to provide index-based access to a teacher's students.
An indexer use in your situation would be a TeachersClass class, which would encapsulate the students (collection) and the current teacher. Although you could do the same thing by exposing the list of students, but it does show you an example.
Here is a code example:
public class TeachersClass
{
private List<Student> _students;
public TeachersClass(Teacher currentTeacher, List<Student> students)
{
CurrentTeacher = currentTeacher;
_students = students;
}
public Teacher CurrentTeacher { get; set; }
public Student this[int studentID]
{
get
{
return (from s in _students
where s.Id = studentID
select s).First();
}
}
}
Random order access
You would use an enumerator if your data is normally accessed sequentially.
An indexer on the other hand is useful for directly accessing a specific element, no specific order.
This of course assumes you know the index of the element you want. Comboboxes for example have always supported two values: the string shown to the user, and the id that belongs with it. You could use the id from a selected item in a combobox to directly access the index of your collection, instead of having to search the collection.
The nice thing about indexers in C# is that you can overload them, so you can access items through different kind of keys.
The simple answer (as stated above) is when the class represents/contains a collection of items, the indexer will return the elements of the collection.
public Student this[int index] { ..
In a more advanced case you can create a default behavior with a class and make it look a bit like a delegate, especially when the class represents a mapping, or a process. For example a class that calculates the cooling rate of a beer in the refrigerator:
Instead of typing
temperature = coorsLight.CalculateFutureTemperature(time);
you can condence this to
temperature = coorsLight[time];
if the expected behavior (and intent) of the class is to return a value.
An indexer is a means to select an element from an aggregate such as an array or collection. While I agree in part with Ian Davis, I think indexers represent something more than public API polish.
Indexers are the primary means of accessing arrays and most of the major classes representing collections in the .NET BCL implemented indexers, presumably to provide a common expernce when dealing with types that aggregate other types.
Because indexers are a standard part of the interface to many of the BCLs collection types, and because these types are heavily used, as developers learn .NET as a platform, it is reasonable to suggest that an expectation is created that collections can be accessed using some type of indexer.
If your type's interface matches the expectations that developers have already, then that type becomes easier to use because the developer doesn't have to think. This is true whether the developers in question are internal to your organization or out there in the wild.
Of course there are situations where having an indexer just doesn't make sense, and if thats the case then don't implement an indexer.
Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
Indexers enable objects to be indexed in a similar manner to arrays.
// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}
Code project
I remember there was this time when I had a long inside a class, and some digits of that particular long meant something (for example if the third digit was a 3 it meant that the chart had a specific type of encoding, horrible system I know but I didn't invent it)
So I did something like this to return the xth digit of the number:
protected int this[int index]
{
get
{
int tempN = Number;
if (index > 0)
{
tempN /= index * 10;
}
return tempN % 10;
}
}
It was protected because a different method used it, so it was kind of a helper. Of course a simple GetDigit(int a) would've been the same thing (and more self-explanatory) but at the time I thought it was one of the few times I thought using an indexer would make sense. Haven't used them since =(.
IMHO, Indexers are probably best if you're trying to spruce up a packaged API - it's not worth the effort for your run of the mill business object.
And if you're making some specialized collection, I'd categorize that as sprucing up your packaged API - even if you keep it all in one module.