Immutable pure data classes with public setters on properties
This is what I program when I want "immutable" classes in C#. You do have an access leak right now though, in that PopularClasses and UnpopularClasses both set and get the underlying object, allowing modification of that object, thus making the class immutable. (This is a bigger problem for set than get, as get would require figuring out which collection type is actually being held. Set you already know because you set it.)

List&lt;string&gt; popularClasses = new List&lt;string&gt;;
popularClasses.add("hello");

pscos = new PopularitySplitClassOptionSet(..., popularClasses, ...);
popularClasses.add("sup"); // This is now added to pscos.

List&lt;string&gt; getAlsoLeaks = (List&lt;string&gt;)(pscos.PopularClasses);
getAlsoLeaks.add("yo"); // This is also added.


You will need to copy on get and set to avoid this. Usually I use LinkedList&lt;T&gt; for this purpose, unless I will need random access, in which case I use List&lt;T&gt;. Since you're only currently using IEnumerable&lt;T&gt;, I'm assuming that random access isn't an issue and using LinkedList&lt;T&gt;.

private LinkedList&lt;ClassOption&gt; popularClasses;
public IEnumerable&lt;ClassOption&gt; PopularClasses
{
    get
    {
        foreach (ClassOption classOption in list.popularClasses)
            yield return classOption;
        // OR:
        // return new LinkedList&lt;ClassOption&gt;(this.popularClasses);
    }
    set
    {
        this.popularClasses = new LinkedList&lt;ClassOption&gt;(value);
    }
}