Here's what MSDN says about the error, and also how you can avoid it.
Here's my take on the issue.
Consider, the following class:
class BigDataClass
{
public List<string> Data { get; set; }
}
This class will throw that exact same issue. Why? Because Collections
do not need a setter. Now, we can do anything with that object: assign Data
to an arbitrary List<string>
, add elements to Data
, remove elements from Data
, etc. If we remove the setter
, we only lose the ability to directly assign to that property.
Consider the following code:
class BigDataClass
{
private List<string> data = new List<string>();
public List<string> Data { get { return data; } } // note, we removed the setter
}
var bigData = new BigDataClass();
bigData.Data.Add("Some String");
This code is perfectly valid and in fact the recommended way to do things. Why? Because the List<string>
is a reference to a memory location, that contains the remainder of the data.
Now, the only thing you cannot now do with this, is directly set the Data
property. I.e. the following is invalid:
var bigData = new BigDataClass();
bigData.Data = new List<string>();
This is not necessarily a bad thing. You'll notice that on many .NET types this model is used. It's the basics of immutability. You usually do not want direct access to the mutability of Collections
, as this can cause some accidental behavior that has strange issues. This is why Microsoft recommends you omit setters.
Example:
var bigData = new BigDataClass();
bigData.Data.Add("Some String");
var l2 = new List<string>();
l2.Add("String 1");
l2.Add("String 2");
bigData.Data = l2;
Console.WriteLine(bigData.Data[0]);
We might be expecting Some String
, but we'll get String 1
. This also means that you cannot reliably attach events to the Collection
in question, so you cannot reliably determine if new values are added or values are removed.
A writable collection property allows a user to replace the collection with a completely different collection.
Essentially, if you only ever need to run the constructor, or assignment, once, then omit the set
modifier. You won't need it, direct assignment of collections is against best-practices.
Now, I'm not saying never use a setter on a Collection
, sometimes you may need one, but in general you should not use them.
You can always use .AddRange
, .Clone
, etc. on the Collections
, you only lose the ability of direct assignment
.
Serialization
Lastly, what do we do if we wish to Serialize
or Deserialize
a class that contains our Collection
without a set
? Well, there is always more than one way to do it, the simplest (in my opinion) is to create a property
that represents the serialized collection.
Take our BigDataClass
for example. If we wished to Serialize
, and then Deserialize
this class with the following code, the Data
property would have no elements.
JavaScriptSerializer jss = new JavaScriptSerializer();
BigDataClass bdc = new BigDataClass();
bdc.Data.Add("Test String");
string serd = jss.Serialize(bdc);
Console.WriteLine(serd);
BigDataClass bdc2 = jss.Deserialize<BigDataClass>(serd);
So, to fix this, we can simply modify our BigDataClass
a bit to make it use a new string
property for Serialization
purposes.
public class BigDataClass
{
private List<string> data = new List<string>();
[ScriptIgnore]
public List<string> Data { get { return data; } } // note, we removed the setter
public string SerializedData { get { JavaScriptSerializer jss = new JavaScriptSerializer(); return jss.Serialize(data); } set { JavaScriptSerializer jss = new JavaScriptSerializer(); data = jss.Deserialize<List<string>>(value); } }
}
Another option is always the DataContractSerializer
(which is really a better option, in general.) You can find information about it on this StackOverflow question.
private
orinternal
? If not I would just suppress the warning. – ZagreusPO1Loop.PIDRepeat1 = new Collection<SegmentTypes.PO1LoopSegmentTypes.PID1>();
outside the class? If you are justadding
,removing
, oraltering
elements within the collections, then remove the unnecessaryset
. – CroweAddRange
on them when you have the values. A better option would be to ignore this suggestion. – TrehalaCollection
there? – Crowe