Reputation: 7005
I am having problems understanding how to correctly encapsulate my class. It is (or should be) an inmutable class.
I am using a "helper class" and I want it to be not accesible from the outside.
namespace MyApp
{
[Flags]
public enum OctaveGroups
{
None = 0,
oneOctave = 1
}
class Frequencies
{
// HelperClass
public class Frequency
{
public string Name { get; set; }
public OctaveGroups Octave { get; set; }
}
public readonly static List<Frequency> All = new List<Frequency>
{
#region Complete Frequencies Data
new Frequency { Name = "63", Hz = 63,
Octave = OctaveGroups.oneOctave | OctaveGroups.None,
},
new Frequency { Name = "80", Hz = 80,
Octave = OctaveGroups.None,
}
// And so on..
//..
#endregion
};
public readonly List<Frequency> OneOctave = All.Where(f => f.Octave.HasFlag(OctaveGroups.oneOctave)).ToList();
public readonly List<Frequency> None = All.Where(f => f.Octave.HasFlag(OctaveGroups.None)).ToList();
}
}
If I make my Frequency
class protected
or private
I get this error:
Inconsistent accessibility: field type 'List' is less accesible than field 'Frequencies.All'
I get the same error if I make class Frequency
and List<Frequency> All
protected and try to make a method that returns a List<Frequency>
like:
public List<Frequency> GetAll()
{
return All.Where(f => f.Octave.HasFlag(OctaveGroups.OneOctave)).ToList();
}
How will be the correct way to expose just .All
.OneOctave
and .None
fields while keeping them read only?
Upvotes: 3
Views: 1599
Reputation: 32770
You can't expect to hide Frequency
when you are planning in having public methods returning List<Frequency>
.
Now, what I understand is your issue is that you need accessible property setters in Frequency
from Frequencies
but you don't want to expose them to the outside. The way to do this is through an interface that only exposes getters:
public interface IFrequency
{
string Name { get; }
OctaveGroups Octave { get; }
}
And now, you make Frequencies.Frequency
a private nested class and you expose only IFrequency
:
class Frequencies
{
// HelperClass
private class Frequency: IFrequency
{
public string Name { get; set; }
public OctaveGroups Octave { get; set; }
}
public readonly static List<IFrequency> All = new List<IFrequency>
{
#region Complete Frequencies Data
new Frequency { Name = "63", Hz = 63,
Octave = OctaveGroups.oneOctave | OctaveGroups.None,
},
new Frequency { Name = "80", Hz = 80,
Octave = OctaveGroups.None,
}
// And so on..
//..
#endregion
};
public readonly List<IFrequency> OneOctave = All.Where(f => f.Octave.HasFlag(OctaveGroups.oneOctave)).ToList();
public readonly List<IFrequency> None = All.Where(f => f.Octave.HasFlag(OctaveGroups.None)).ToList();
}
Now a consumer of Frequencies
will only see IFrequency
instances where no setter is exposed and is therefore immutable to the outside world (excluding reflection of course).
Upvotes: 6
Reputation: 39
Try adding an internal constructor to your Frequency class. This will allow you to construct a Frequency from within the class but disallow outside classes from constructing it. Since it can't be constructed on the outside no one outside of the class will be able to add a new one to your Lists since they are typed to Frequency.
Example:
public class ExternalType
{
public class InternalType
{
internal InternalType(string someString)
{
SomeStringProp = someString;
}
public string SomeStringProp { get; private set; }
}
public readonly List<InternalType> InternalTypes = new List<InternalType>()
{
new InternalType("test")
};
}
If you try to instantiate InternalType outside of ExternalType you will get a compiler error. However your dependents will be able to read the list.
Upvotes: -1
Reputation: 391446
The correct way is not to hide them.
You simply cannot both hide and expose a class to the outside world, at the same time.
So if you want to declare a public method returning the object, or a collection of the object, you must make the type of the object in question public as well.
Upvotes: 2