I want to create a immutable Scale
class in C#.
public sealed class Scale
{
string _Name;
string _Description;
SomeOrderedCollection _ScaleValueDefinitions;
Unit _Unit
// properties
....
// methods
ContainsValue(double value)
....
// constructors
// all parameters except scalevaluedefinitions are optional
// for a Scale to be useful atleast 1 ScaleValueDefinition should exist
public Scale(string name, string description, SomeOrderedCollection scaleValueDefinitions, unit)
{ /* initialize */}
}
so first a ScaleValueDefinition
should be represented by to values:
- Value (double)
- Definition (string)
these values are known before the Scale class is created and should be unique.
so what is the best approach.
- create a immutable class ScaleValueDefinition with value and definition as properties and use it in a list.
- use a dictionary.
- use another way i didn’t think of…
and how to implement it.
for option 1. i can use params ScaleValueDefinition[] ValueDefinitions
in the constructor, but how to do it for the other options?
and as last at what amount of value’s (properties) should i choose one option over the other?
1
like this maybe?
public sealed class Scale<TUnit> : IReadOnlyList<TUnit>
{
private readonly string name;
private readonly string description;
private readonly IList<TUnit> definition;
public Scale(
string name,
string description,
IEnumerable<TUnit> definition) : this(name, description)
{
this.definition = definition.ToList();
}
public Scale(
string name,
string description,
params TUnit[] definition) : this(name, description)
{
this.definition = definition;
}
private Scale(
string name,
string description)
{
this.name = name;
this.description = description;
}
public string Name
{
get { return this.name; }
}
public string Description
{
get { return this.description; }
}
public TUnit this[int index]
{
get { return this.definition[index]; }
}
public int Count
{
get { return this.definition.Count; )
}
public IEnumerator<TUnit> GetEnumerator()
{
return this.definition.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
3
It’s rather opinion based but explicit classes seem to be better as they really express your intent. Also, code is easier to maintain – imagine changing keys of your dictionary all over the code, whereas for a class one place refactoring would suffice.
You haven’t mentioned whether you will need to look up definitions by their value, which of course is the main purpose of a dictionary. Otherwise, I don’t see any reason to use a dictionary.
If you need to do lookups, I would actually use both: that is, a Dictionary<double, ScaleValueDefinition>
. That way, I can look up the definitions by the value, but also retain a reference to the value I looked up. This also means the dictionary can be dynamically generated from a sequence of ScaleValueDefinitions (using ToDictionary), and the order of that sequence can be stored, without forcing the user to pass in an OrderedDictionary:
private IEnumerable<ScaleValueDefinition> _internalOrderedCollection;
private Dictionary<double, ScaleValueDefinition> _internalDictionary;
public Scale(string name, string description, IEnumerable<ScaleValueDefinition> scaleValueDefinitions) {
_name = name;
_description = description;
_internalOrderedCollection = scaleValueDefinitions.ToList();
_internalDictionary = scaleValueDefinitions.ToDictionary(svd => svd.Value);
}
For immutability, you can simply wrap the internal dictionary in a public ReadOnlyDictionary.
3