Correct usage of properties when dealing with a collection - c#

I am wondering what is the best way to use properties when dealing with collections.
For example I have a class Foo and I want to have a list of that class stored. Which of the following should be used:
private List<Foo> myList;
private List<Foo> myOtherList = new List<Foo>();
now for the property:
public List<Foo> ListOfFoo
{
get
{
return myList;
}
set
{
myList= new List<Foo>(value);
}
}
Or should the set just be to the value?
public List<Foo> ListOfFoo
{
get
{
return myList;
}
set
{
myList= value;
}
}

Choose
private List<Foo> myOtherList = new List<Foo>();
becuse the other just declares a reference (which is set to null), the sample above declares a reference to a list, creates a list and assignes that new list to the reference.
Choose
public List<Foo> ListOfFoo
{
get { return myList; }
set { myList= new List<Foo>(value); }
}
When you want myList to NOT refelect any changes that happen to the list after it is assigned to myList e.g.
List<string> myFirstList = new List<string>();
myFirstList.Add("Hello");
myFirstList.Add("World");
List<string> mySecondList = new List<string>(myFirstList);
// mySecondList now contains Hello & world
myFirstList.Add("Boyo");
// myFrist List now contains Hello, world & Boyo
// mySecondList still contains Hello & world
Choose
public List<Foo> ListOfFoo
{
get { return myList; }
set { myList= value; }
}
When you want both references to point to the same object e.g.
List<string> myFirstList = new List<string>();
myFirstList.Add("Hello");
myFirstList.Add("World");
List<string> mySecondList = myFirstList;
// mySecondList now contains Hello & world
myFirstList.Add("Boyo");
// myFrist List now contains Hello, world & Boyo
// mySecondList "also" contains Hello, world & Boyo
The "also" above is in quotes, because actually, there is only one list, and both my first and my second point to the same list.

Generally you don't want to use properties of a rich type like List<T> (normally one would use Collection<T>), and generally properties of a collection type are read-only - the collection itself can be modified with methods like Clear, Add etc., and this is normally sufficient.
For example:
class Foo
{
Collection<Bar> _bars = new Collection<Bar>();
public Collection<Bar> Bars { get { return _bars; } }
}
This also leaves you open to validate modifications to the collection by implementing a descendant of Collection<T> and overriding the InsertItem, SetItem etc. methods.

It depends.
When the first style is used, you create a copy of the list, which is generally unnecessary. .Net convention is for the setter to assign the reference to the property. This is why I would lean towards the second option.
However, if you are intending for the copy operation to take place, the first option is what you are looking for.

Generally, expose only an Interface (ICollection, IList or similar), and make it readonly:
private IList<Foo> m_list = new List<Foo>();
public IList<Foo> List {get { return m_list; } }
Advantage: You can modify the implementation, e.g. switch from a List to an Observable List. You might need to make the m_list member of the concrete type rather than the interface, e.g. to use additional funcitonality.
With an settable external list, you run into a few problems. However, there are some cases where this is needed:
the data can be created externally, and is potentially large, and changes frequently (e.g. tens of thousands of items)
the external list should be shared between different instances

Why not use the IEnumerator-Interface on the class and if you have to use a setter, use a certain method.
This way you are hiding the actual List-Implementation as well.
class FooBar : IEnumerator
{
private Collection<Foo> col;
public IEnumarator GetEnumerator()
{
return col.GetEnumerator();
}
public void SetList(Collection col)
{
this.col= col; // you can also make this more general and convert the parameter so it fits your listimpl.
}
}
class Clazz
{
private void WhatEver(){
FooBar foobar = new FooBar();
...
foreach(Foo f in foobar)
{...}
}
}

Related

How to Ensure Immutability of a Generic

This example is in C# but the question really applies to any OO language. I'd like to create a generic, immutable class which implements IReadOnlyList. Additionally, this class should have an underlying generic IList which is unable to be modified. Initially, the class was written as follows:
public class Datum<T> : IReadOnlyList<T>
{
private IList<T> objects;
public int Count
{
get;
private set;
}
public T this[int i]
{
get
{
return objects[i];
}
private set
{
this.objects[i] = value;
}
}
public Datum(IList<T> obj)
{
this.objects = obj;
this.Count = obj.Count;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return this.objects.GetEnumerator();
}
}
However, this isn't immutable. As you can likely tell, changing the initial IList 'obj' changes Datum's 'objects'.
static void Main(string[] args)
{
List<object> list = new List<object>();
list.Add("one");
Datum<object> datum = new Datum<object>(list);
list[0] = "two";
Console.WriteLine(datum[0]);
}
This writes "two" to the console. As the point of Datum is immutability, that's not okay. In order to resolve this, I've rewritten the constructor of Datum:
public Datum(IList<T> obj)
{
this.objects = new List<T>();
foreach(T t in obj)
{
this.objects.Add(t);
}
this.Count = obj.Count;
}
Given the same test as before, "one" appears on the console. Great. But, what if Datum contains a collection of non-immutable collection and one of the non-immutable collections is modified?
static void Main(string[] args)
{
List<object> list = new List<object>();
List<List<object>> containingList = new List<List<object>>();
list.Add("one");
containingList.Add(list);
Datum<List<object>> d = new Datum<List<object>>(containingList);
list[0] = "two";
Console.WriteLine(d[0][0]);
}
And, as expected, "two" is printed out on the console. So, my question is, how do I make this class truly immutable?
You can't. Or rather, you don't want to, because the ways of doing it are so bad. Here are a few:
1. struct-only
Add where T : struct to your Datum<T> class. structs are usually immutable, but if it contains mutable class instances, it can still be modified (thanks Servy). The major downside is that all classes are out, even immutable ones like string and any immutable class you make.
var e = new ExtraEvilStruct();
e.Mutable = new Mutable { MyVal = 1 };
Datum<ExtraEvilStruct> datum = new Datum<ExtraEvilStruct>(new[] { e });
e.Mutable.MyVal = 2;
Console.WriteLine(datum[0].Mutable.MyVal); // 2
2. Create an interface
Create a marker interface and implement it on any immutable types you create. The major downside is that all built-in types are out. And you don't really know if classes implementing this are truly immutable.
public interface IImmutable
{
// this space intentionally left blank, except for this comment
}
public class Datum<T> : IReadOnlyList<T> where T : IImmutable
3. Serialize!
If you serialize and deserialize the objects that you are passed (e.g. with Json.NET), you can create completely-separate copies of them. Upside: works with many built-in and custom types you might want to put here. Downside: requires extra time and memory to create the read-only list, and requires that your objects are serializable without losing anything important. Expect any links to objects outside of your list to be destroyed.
public Datum(IList<T> obj)
{
this.objects =
JsonConvert.DeserializeObject<IList<T>>(JsonConvert.SerializeObject(obj));
this.Count = obj.Count;
}
I would suggest that you simply document Datum<T> to say that the class should only be used to store immutable types. This sort of unenforced implicit requirement exists in other types (e.g. Dictionary expects that TKey implements GetHashCode and Equals in the expected way, including immutability), because it's too difficult for it to not be that way.
Kind of hacky, and definitely more confusing than it's worth in my opinion, but if your T is guaranteed to be serializable, you can store string representations of the objects in your collection rather than storing the objects themselves. Then even if someone pulls an item from your collection and modifies it, your collection would still be intact.
It would be slow and you'd get a different object every time you pulled it from the list. So I'm not recommending this.
Something like:
public class Datum<T> : IReadOnlyList<T>
{
private IList<string> objects;
public T this[int i] {
get { return JsonConvert.DeserializeObject<T>(objects[i]); }
private set { this.objects[i] = JsonConvert.SerializeObject(value); }
}
public Datum(IList<T> obj) {
this.objects = new List<string>();
foreach (T t in obj) {
this.objects.Add(JsonConvert.SerializeObject(t));
}
this.Count = obj.Count;
}
public IEnumerator<T> GetEnumerator() {
return this.objects.Select(JsonConvert.DeserializeObject<T>).GetEnumerator();
}
}
It's impossible. There's no possible way to constrain the generic type to be immutable. The best that you can possibly do is write a collection that cannot allow the structure of that collection to be modified. There is no way to prevent the collection from being used as a collection of some mutable type.
think that such collections are not match OOP, because this design leads to specific co-relation between independent classes - collection and it's items. How one class can change behavior of other without knowlege of each other?
So suggestions of serialization and so can allow you to do it on hacky way, but better is to decide if it's so required to make collection of immutable items, who trys to change them except your own code? May be better "to not mutate" items rather than try "make them immutable".
I faced the same problem, where I implement an object (say CachedData<T>) which handles a cached copy of the property of another object (say T SourceData). When calling the constructor of CachedData, you pass a delegate which returns a SourceData. When calling CachedData<T>.value, you get a copy of SourceData, which is updated every now and then.
It would make no sense to try caching an object, as .Value would only cache the reference to the data, not the data itself. It would only make sense to cache data types, strings, and perhaps structures.
So I ended up:
Thoroughly documenting CachedData<T>, and
Throwing an error in the constructor if T is neither a ValueType, a Structure, or a String. Some like (forgive my VB): If GetType(T) <> GetType(String) AndAlso GetType(T).IsClass Then Throw New ArgumentException("Explain")

Accessor for formatted sub-list of dictionary possible without creating a new object every time?

first off - yes, I had a look at this question: Is object creation in getters bad practice?.
I am also not talking about initializing an object in the accessors / mutators, it is about a specific part of the object I want to be returned in a specific way.
My question is more specific; It does not necessarily only apply to C#, however I am currently looking for a solution to implement in my C# project.
I have a class with a dictionary that maps date objects to a decimal value. In one accessor, I want to return a list of all the keys of the dictionary, another accessors returns the values.
What I also want to have is an accessor that gives me the decimal values in a specific format. It would look something like this:
class Class
{
// Some other properties...
// ....
private Dictionary<DateTime, decimal> dict;
public Class(Dictionary<DateTime, decimal> dict)
{
this.dict = dict;
}
private string FormatTheWayIWant(decimal dt)
{
// Format decimal value.
string s = String.Format("{0:F}", dt);
return s;
}
public ReadOnlyCollection<DateTime> DateTimes
{
get { return new ReadOnlyCollection<DateTime>(this.dict.Keys.ToList()); }
}
public ReadOnlyCollection<decimal> Values
{
get { return new ReadOnlyCollection<decimal>(this.dict.Values.ToList()); }
}
public ReadOnlyCollection<string> FormattedStrings
{
get
{
// Format each decimal value they way I want.
List<string> list = new List<string>();
foreach (decimal dt in dict.Keys)
{
list.Add(FormatTheWayIWant(dt));
}
return new ReadOnlyCollection<string>(list);
}
}
}
This way I can make the following calls (which is my goal!):
DateTime dateTime = DateTimes[0];
decimal s = Values[0];
string formattedS = FormattedStrings[0];
The problem with this approach is that I create a new list everytime I invoke the FormattedStrings accessor, even if I only need one of the formatted strings. I know this is not good practice and can introduce unnecessary performance issues...
The alternatives I thought of are:
I could extend the decimal class and implement a custom ToString()-method.
Or overwrite the KeyValuePair<DateTime, decimal> class and use an indexer in my class.
Or I create a method with a parameter for the index and return just the one formatted string.
Or I could have an own list for the accessor, which gets updated in the set-method for my dictionary everytime I update the dictionary.
The question I have is, is there a way to make this work with an accessor instead of a method, creating custom classes or having strange side effects on other objects when assigning a value?
Thank you in advance.
Ofcourse this can be done with an accessor. You just have to create 3 separate classes for each desired element of your processed collection. Those classes should have their own indexers, so you would be able to access the elements as a list. The difference would be, that they compute each element on demand (wchich is called lazy initialization). So it would go like this (example for your FormattedStrings):
class Class
{
// ...
MyFormattedStrings FormattedStrings
{
get {return new MyFormattedStringsIndexer<string>(this.dict.Values.ToList());}
}
}
class MyFormattedStringsIndexer<T>
{
private IList<T> list; // we take only reference, so there is no overhead
public MyFormattedStringsCollection (IList<T> list)
{
this.list = list;
}
// the indexer:
public T this[int i]
{
get
{
// this is where the lazy stuff happens:
// compute the desired element end return it
}
set
{
// ...
}
}
}
Now you can use your Class like this:
string formattedS = FormattedStrings[5];
and each element you access will be computed as you access it. This solution also has the advantage of separating concerns, so should you ever had to implement different logic for one of your 3 accessors it would be just a matter of extending one of the indexers.
You can read more about indexeres here: http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
This is VB, but you get the idea...
Public Class Something
Public Property Items As Dictionary(Of DateTime, String)
Public Readonly Property FormattedItem(ByVal index As Int32) As String
' add error checking/handling as appropriate
Return Me.Items.Keys(index).ToString("custom format") ' or whatever your formatting function looks like.
End Property
End Class
It looks like a good candidate for a new class
public class MyObject
{
public DateTime Key {get;set;}
public String Name {get;set;}
public String FormattedString {get;}
}
And then it can be used in any container (List<MyObject>, Dictionary<MyObject>, etc).
Your Dates and Strings property getters are returning a new list on each call. Therefore if a caller does the following:
Class myClass = ...
for(i=0; i<myClass.Strings.Count; i++)
{
var s = myClass.Strings[i];
...
}
then each iteration of the loop will create a new list.
I'm not clear on what you're really trying to achieve here. You are wrapping the dictionary's Keys and Values properties in ReadOnlyCollections. This gives you an indexer, which doesn't have much meaning as the order of the Keys in a Dictionary<TKey, TValue> is unspecified.
Coming (at last!) to your question, if you want to do the formatting in a "lazy" manner, you could create a custom class that implements a readonly IList<string>, and wraps your list of keys (IList<DateTime>). Most of the implementation is boilerplate, and your indexer will do the formatting. You could also cache the formatted values so that you only format once if accessed multiple times. Something like:
public class MyFormattingCollection : IList<string>
{
private IList<decimal> _values;
private IList<string> _formattedValues;
public MyFormattingCollection(IList<DateTime> values)
{
_values = values;
_formattedValues = new string[_values.Count];
}
public string this[int index]
{
get
{
var result = _formattedValues[index];
if (result == null)
{
result = FormatTheWayIWant(_values[index]);
_formattedValues[index] = result;
}
return result;
}
set
{
// Throw: it's a readonly collection
}
}
// Boilerplate implementation of readonly IList<string> ...
}

Property Accessors on List<T> in .NET

I have a property called Fruits which contains a comma delimited string in the form "apples,bananases,peaches"
I want to make a list in the same class which makes the Fruits property easier to manipulate. Accessors won't work as they are not supported on lists or so it seems.
Basically i want a property called FruitList which auto populates based on the Fruits Property and when adding items or manipulating the FruitList it should auto populate the fruits property.
I need the Fruits Property for Entity framework.
You can invert the logic:
List<string> fruitsList = new List<string>();
public List<string> FruitsList
{
get
{
return fruitsList;
}
}
public string Fruits
{
get
{
return string.Join(',', fruitsList);
}
set
{
// Incomplete, does not handle null
FruitsList.Clear();
FruitsList.AddRange(value.Split(','));
}
}
You don't need to worry about updating Fruits if Fruits is determined by looking at FruitsList. You mention that you need Fruits as a string property for Entity Framework, but EF does not care whether it is backed by a string field.
The only realistic way to do this is to use a collection which can be observed for changes, and handle the event raised when it is changed, and update the property.
Something like ObservableCollection<T> would fit the bill.
example:
public class MyObject
{
public string Fruits{get;set;}
public IList<string> FruitList
{
get
{
var list = new ObservableCollection<string>(Fruits.Split(','));
list.CollectionChanged += (s,ea) => {
var items = (IList<string>)s;
Fruits = String.Join(",",items);
};
return list;
}
}
}
Usage:
var obj= new MyObject(){ Fruits="Apple,Banana,Orange" };
var list = obj.FruitList;
list.Add("Satsuma");
list.Add("Grapes");
list.Remove("Apple");
Console.WriteLine(obj.Fruits); // Output: Banana,Orange,Satsuma,Grapes
Live example: http://rextester.com/KCT33825
Having seen the concept here work, it's worth noting that the above implementation is frought with a bit of danger. It creates a new ObservableCollection every time you call the get accessor on it, which could have some unintended consequences.
For example, if you add the following line just before my original Console.WriteLine:
Console.WriteLine("{0}", obj.FruitList == list);
It outputs false which might seem strange as you might (and notionally, should) expect list and obj.FruitList to point to the same list.
You can get round this by changing the implementation to create only ever 1 ObservableCollection and always returning that from the get accessor:
public class MyObject
{
private string fruits;
private ObservableCollection<string> fruitList;
public string Fruits
{
get{ return this.fruits; }
set
{
this.fruits = value;
this.fruitList = CreateFruitList();
}
}
private ObservableCollection<string> CreateFruitList()
{
var list = new ObservableCollection<string>(this.fruits.Split(','));
list.CollectionChanged += (s,ea) => {
var items = (IList<string>)s;
this.fruits = String.Join(",",items);
};
return list;
}
public IList<string> FruitList
{
get
{
return fruitList;
}
}
}
Now all is right with the world again!
here's what you could do, create a proxy for your comma separated list:
public class MyClass
{
public string Fruits {get;set;}
public string [] FruitList {
get { return Fruits.Split(new [] {','}); }
//warning, the setter is dangerous
set { Fruits = string.Join(',', value); }
}
}
When I say the setter is dangerous, I only mean that if you change one element of the array, the Fruit won't be updated. It'll only be updated if you push a new array. If you need that behavior, consider implementing it using an ObservableCollection

What is the best way to expose a List<T> as readonly?

I've been around this design problem many times, and never found a killer solution.
I want to expose a collection that is editable in the owner class scope, but only readable for other public scopes.
Trial 1:
public class MyClass
{
private List<object> _myList = new List<object>();
public IEnumerable<object> MyList { get { return _myList; } }
}
The problem with this is a external code can just cast it back to List and edit, like this:
var x = ((List<object>)MyList);
Trial 2:
public class MyClass
{
private List<object> _myList = new List<object>();
public IEnumerable<object> MyList { get { return _myList.ToList(); } }
}
This way we prevent external modification, but create a unnecessary overhead of copying the List many times.
Trial 3:
public class MyClass
{
private List<object> _myList = new List<object>();
private ReadOnlyCollection<object> _roList =
new ReadOnlyCollection<object>(_myList)
public IEnumerable<object> MyList { get { return _roList; } }
}
This is the standard solution, wich I use currently, but ReadOnlyCollection is about 30% slower:
Debug Trace:
Use normal foreach on the ReadOnlyCollection
Speed(ms): 2520,3203125
Result: 4999999950000000
use<list>.ForEach
Speed(ms): 1446,1796875
Result: 4999999950000000
Use normal foreach on the List
Speed(ms): 1891,2421875
Result: 4999999950000000
Is there a 'perfect' way of doing this? Thanks.
Have you tried returning the enumerator?
public class MyClass
{
private List<object> _myList = new List<object>();
public IEnumerable<object> MyList { get { yield return _myList.GetEnumerator(); } }
}
This doesn't create a copy, is readonly, and cannot be cast back to list.
Edit: this only works with yield return. It is lazy evaluated this way, I do not know whether that is an issue for you or not.
You can use List<T>.AsReadOnly method to expose a thin read-only wrapper of your list. There will be no additional copying, and the caller will "see" changes to the original array done inside your method instantaneously:
public ReadOnlyCollection<object> MyList { get { return _myList.AsReadOnly(); } }
List<T> implements IReadOnlyList<T>:
public class MyClass
{
private List<object> _myList = new List<object>(); // Modifiable
public IReadOnlyList<object> MyList => _myList; // Read only
}
The solution I usually use and like a lot because it is simple is the following one:
public IEnumerable<object> MyList { get { return _myList.Select(x => x); } }
However, it requires you to use a version of .NET that supports Linq
For looping over it with a foreach it's actually faster: less than 1ms for the Select and 0.1 second for the ReadOnlyCollection. For the ReadOnlyCollection, I used:
public IEnumerable<object> MyROList { get { return new ReadOnlyCollection<object>(_myList); } }
Use ReadOnlyCollection<T> as a wrapper - it uses your List<T> collection internally (using the same reference, so it doesn't copy anything, and any changes made to the List are also reflected in the ReadOnlyCollection).
It's better than just offering an IEnumerable property because it also offers indexing and count information.
.NET Framework 4.5 introduces two new interfaces: IReadOnlyCollection<T> and IReadOnlyList<T>. List<T> implements both interfaces.
Why don't you use List<T>.AsReadOnly method, see the code snippet below:
public class MyClass
{
private List<object> _myList = new List<object>();
public IList<object> MyList { get { return _myList.AsReadOnly(); } }
}

convert a generic list to ISet

Has anyone had to assign a list to an ISet? How do I go about and do this?
Say I have the class
class Foo
{
ISet<Item> Items { get; set; }
}
Now, I want to do the following:
var foo = new Foo() { Items = new List<Item>() { new Item() } }
List<Item> myList = ...
foo.Items = new HashSet<Item>( myList );
Keep in mind that a Set, unlike a List, must contain every element exactly once. Therefore, if myList contains multiple copies of some elements, all those copies, except one, will not make it into the set.
Equality of elements (for detecting multiple copies) is defined by the Equals and GetHashCode methods. If you would like to use a different definition of equality, you can use the overload of HashSet constructor that takes an IEqualityComparer<Item>.
List<T> doesn't implement the ISet<T> interface… So, this isn't possible.
The only classes that implement ISet<T> are HashSet<T> and SortedSet<T>.
The closest you could get would be (if you cut out the unnecessary List object in between):
var foo = new Foo { Items = new HashSet<Item> { new Item() } };

Categories

Resources