I'm making a Phone Book console application in c# and It's my biggest project so far :) I consider myself as a beginner but I would love to improve
I am using 3 classes to create this, here they are:
Modifications class is responsible for adding, deleting and editing contacts. Search and Display classes are self explanatory. I also have interfaces for each of these classes.
I created a List of KeyValuePair inside Modifications class, like this:
private List<KeyValuePair<string , int>> AllContacts { get; set; }
public Modifications()
{
AllContacts = new List<KeyValuePair<string, int>>();
}
I would like to access this AllContacts
object in my other classes. But I failed to achieve this while maintaining encapsulation. AllContacts
is like my main source of data. I add contacts in this List. I don't want someone in my main method to be like modificationObject.AllContacts.Clear();
[ skip this if you prefer :) ]
My Sad Attempt Part 1:
-Inherited Display Class from base class Modifications
-in my Modifications class, I created a protected property of type List<KeyValuePair<string , int>>
and named it 'AllContacts' as a database
-in my Display class , I created a private property of same type as above and named it _allContacts
-inside Constructor of my Display class, I requested a Modification type object named it modObject
-I stated , _data = modObject.AllContacts;
-It didnt work, I presume it's because only derived objects are able to get this property?
My Sad Attempt Part 2:
-Assuming my assumption is true, I tried to downcast the modObject to its derived class type, Display. Got compilation error instead. Tried to make a protected GetAllContacts()
method, compilation error.
My Sad Attempt Part 6:
-In end, I just made it a public property with a private setter. My application works, But people could still go x.AllContacts.Clear()
in my main method somehow.
How can I use AllContacts
object in other classes without breaking encapsulation? Is it even possible?
Initially, I created a separate class for data and I had 3 other classes (Modification, Search and Display) , its a better design, right? I had same problem in accessing that data object in my other classes.
Thanks :)
Modification class:
public class Modifications
{
public List<KeyValuePair<string, int>> AllContacts { get; private set; }
public Modifications()
{
AllContacts = new List<KeyValuePair<string, int>>();
}
....
Display class:
public class Display : IDisplayable
{
private List<KeyValuePair<string, int>> AllContacts;
public Display(Modifications modificationsObject)
{
AllContacts = modificationsObject.AllContacts;
}
....
You don't need to declare accessors for a private variable member unless you want to disallow the setter for all others methods but it is more speed optimized to use readonly field than property that avoid useless CPU Proc Calls that consume ticks timings for nothing.
To access it from other classes you must declare it as public like that:
public List<KeyValuePair<string , int>> AllContacts { get; private set; }
So others classes can read the reference and invoke variables accessors and methods of the List instance like Count and Add but they can't replace this instance reference and thus change the object itself.
But if you want to disallow manipulating of the list, you may implement all wrapped methods you want to expose like Count, Add, Delete, Remove and so on as well as indexer and you can indicate that the class implements IExumerable<KeyValuePair<string , int>>
.
By this way you can have a strong encapsulation:
public class MyClass: IEnumerable<KeyValuePair<string , int>>
{
private readonly List<KeyValuePair<string , int>> AllContacts
= new List<KeyValuePair<string , int>>();
public int ContactsCount
{
get { return AllContacts.Count; }
}
public KeyValuePair<string , int> this[int index]
{
get { return AllContacts[index]; }
set { AllContacts[index] = value; } // don't declare if readonly
}
// if adding is allowed
public int Add(KeyValuePair<string , int> item)
{
...
}
...
}