Arne Vajhøj said:
Assume I have a class where I have some fields which could be of type
string[], List<T> and member of
a single Car object for example. To all these is the class holding a
reference.
Now to my question if some client class need to a reference to all these
for
example should I then always
make a copy of the referenced object and then return the reference to the
copy.
Like I do here.
public List<FoodItem> FoodList
{
get
{
return new List<FoodItem>(m_foodItemList);
}
}
If I do that I will of course loose performance.
So what is your opinion in this matter ?
I would still recommend:
public List<FoodItem> FoodList
{
get
{
return m_foodItemList.AsReadOnly();
}
}
because that one does not copy the data - it only
wraps access to the data.
This means that a client that only needs to read data
does not copy. A client that needs to modify data can
then create a copy of data and do whatever.
But I think that is better than allways creating
a copy just in case someone want to modify a copy.
Arne
This cause problem look at the two classes I have here and at the end I have
a method called InitFoodItems that I use from the GUI class. This method
InitFoodItems I use to add some items to a checkedListBox.
The first problem is that I have a set and a get for the Ingredients
property.
The second problem is that I use InitFoodItems method in a way that a
string[] is required as you can see here
checkedListBox.Items.Add(string.Format(foodItem.Name + " (" +
string.Join(",", foodItem.Ingredients) + ")"));
***********************************
Class FoodManager
**********************************
class FoodManager
{
private List<FoodItem> m_foodItems = new List<FoodItem>();
public FoodManager()
{}
public int Count
{
get { return m_foodItems.Count; }
}
public void Add(FoodItem foodItem)
{
m_foodItems.Add(foodItem);
}
public List<FoodItem> GetFoodItemList()
{
return new List<FoodItem>(m_foodItems);
}
public void Reset()
{
m_foodItems.Clear();
}
public FoodItem this[string name]
{
get
{
return (FoodItem)m_foodItems.Find(delegate(FoodItem item) {
return item.Name == name; }).GetCopy();
}
}
}
***********************************
Class FoodItem
**********************************
public enum FoodItemNames
{
MixedFood, Vegeterian, Meat
}
class FoodItem : IAnimalFood
{
private string name;
private string[] ingredients;
private string[] copyOfingredients;
public FoodItem(string name, params string[] ingredients)
{
this.name = name;
this.ingredients = ingredients;
}
#region IAnimalFood Members
public string Name
{
get { return name; }
set { name = value; }
}
public string[] Ingredients
{
get
{
copyOfingredients = new string[ingredients.Length];
Array.Copy(ingredients, copyOfingredients, ingredients.Length);
return copyOfingredients;
}
set { ingredients = value; }
}
public bool IsGoodFor(EaterType eaterType)
{
bool status = false;
switch (eaterType)
{
case EaterType.Carnivora:
if (name.ToLower() ==
FoodItemNames.Meat.ToString().ToLower())
status = true;
else
status = false;
break;
case EaterType.Herbivore:
if (name.ToLower() ==
FoodItemNames.Vegeterian.ToString().ToLower())
status = true;
else
status = false;
break;
case EaterType.Omnivorous:
if (name.ToLower() ==
FoodItemNames.MixedFood.ToString().ToLower())
status = true;
else
status = false;
break;
}
return status;
}
#endregion
#region ICloneable Members
public object GetCopy()
{
return MemberwiseClone();
}
#endregion
}
private void InitFoodItems()
{
foodManager.Add(new FoodItem(FoodItemNames.MixedFood.ToString(),
"carrots", "beef", "milk"));
foodManager.Add(new FoodItem(FoodItemNames.Vegeterian.ToString(),
"cauliflower", "celery", "broccoli","fruits", "leaves", "roots","seeds"));
foodManager.Add(new FoodItem(FoodItemNames.Meat.ToString(),
"meat"));
foreach (FoodItem foodItem in foodManager.GetFoodItemList())
{
checkedListBox.Items.Add(string.Format(foodItem.Name + " (" +
string.Join(",", foodItem.Ingredients) + ")"));
}
}
//Tony