Is it possible to restrict public enum values in C#? - c#

I am currently writing a software program for a tour, made up of exhibits. The exhibit object, at any given point, is in one of four states, defined by the ExhibitStates enum:
private enum ExhibitState { Ready, Active, Complete, Inactive };
For developers who will be setting up exhibits, there are only two "starting" states that I want them to be able to choose from:
public enum StartingExhibitState { Ready, Inactive };
Currently, I have it set up so that upon being initialized, the exhibit will immediately set its state to match its starting state, like so:
switch (startingState) {
case StartingExhibitState.Ready:
SetState(ExhibitState.Ready);
break;
case StartingExhibitState.Inactive:
SetState(ExhibitState.Inactive);
break;
}
I found myself wondering today if this was the best practice. Is there a better way to restrict which enum options are public and which are private? Or is it best to simply have the two separate enums?
Thank you so much for your time.

If you create second enum - your intents will be very clearly explained through signature of setting method
public enum ExhibitState
{
Inactive = 0,
Active = 1,
Ready = 2,
Complete = 3
};
public enum InitialStates
{
Inactive = ExhibitState.Inactive,
Ready = ExhibitState.Ready
};
public void SetInitial(InitialStates state)
{
SetState((ExhibitState)state);
}
If you go further you can add compiler help for preventing passing wrong values to the method.
public sealed class InitialState
{
public static readonly InitialState Initial = new InitialState(ExhibitState.Initial);
public static readonly InitialState Ready = new InitialState(ExhibitState.Ready);
public ExhibitState State { get; }
private InitialState(ExhibitState state)
{
State = state;
}
}
Constructor made private to prevent instantiating class from else where.
Class marked as sealed to prevent deriving and changing it behaviour.
Then your method will look like
public void SetInitial(InitialState start)
{
SetState(start.State);
}
// use it
SetInitial(InitialState.Initial);
SetInitial(InitialState.Ready);
Nothing else cannot be passed, until you change code of InitialState class.

Instead of using an enum (or two of them), you could use a class-based approach:
public abstract class ExhibitState
{
public static ExhibitInitialState Ready { get { return new ExhibitReadyState(); } }
public static ExhibitInitialState Inactive { get { return new ExhibitInactiveState(); } }
public static ExhibitState Complete { get { return new ExhibitCompleteState(); } }
public static ExhibitState Active { get { return new ExhibitActiveState(); } }
private class ExhibitReadyState : ExhibitInitialState {}
private class ExhibitInactiveState : ExhibitInitialState {}
private class ExhibitCompleteState : ExhibitState {}
private class ExhibitActiveState : ExhibitState {}
}
public abstract class ExhibitInitialState : ExhibitState {}
The above sample shows a simple approach. Usually, you'd not create a new instance of a state in the get methods, but have static instances so that comparing is easier.
Similar to an enum, you could still type ExhibitState.Ready or the other states. In addition, the base class ExhibitInitialState allows you to limit the states that can be set initially:
public void SetInitial(ExhibitInitialState initState) { ... }
In comparison to the approach that #Fabio proposed, you'd have the benefit that you could not mix up the values. Furthermore and especially relevant for states: is very common that the behavior should also change for a specific state. With this class-based approach, you could implement this behavior in the specific ExhibitState implementations and by that avoid lots of switch statements that are likely to exist in an enum-based approach.

Related

Refactoring to make code open for extensions but closed for modifications

For my project purpose I need to send metrics to AWS.
I have main class called SendingMetrics.
private CPUMetric _cpuMetric;
private RAMMetric _ramMetric;
private HDDMetric _hddMetric;
private CloudWatchClient _cloudWatchClient(); //AWS Client which contains method Send() that sends metrics to AWS
public SendingMetrics()
{
_cpuMetric = new CPUMetric();
_ramMetric = new RAMMetric();
_hddMetric = new HDDMetric();
_cloudwatchClient = new CloudwatchClient();
InitializeTimer();
}
private void InitializeTimer()
{
//here I initialize Timer object which will call method SendMetrics() each 60 seconds.
}
private void SendMetrics()
{
SendCPUMetric();
SendRAMMetric();
SendHDDMetric();
}
private void SendCPUMetric()
{
_cloudwatchClient.Send("CPU_Metric", _cpuMetric.GetValue());
}
private void SendRAMMetric()
{
_cloudwatchClient.Send("RAM_Metric", _ramMetric.GetValue());
}
private void SendHDDMetric()
{
_cloudwatchClient.Send("HDD_Metric", _hddMetric.GetValue());
}
Also I have CPUMetric, RAMMetric and HDDMetric classes that looks pretty much similar so I will just show code of one class.
internal sealed class CPUMetric
{
private int _cpuThreshold;
public CPUMetric()
{
_cpuThreshold = 95;
}
public int GetValue()
{
var currentCpuLoad = ... //logic for getting machine CPU load
if(currentCpuLoad > _cpuThreshold)
{
return 1;
}
else
{
return 0;
}
}
}
So the problem I have is that clean coding is not satisfied in my example. I have 3 metrics to send and if I need to introduce new metric I will need to create new class, initialize it in SendingMetrics class and modify that class and that is not what I want. I want to satisfy Open Closed principle, so it is open for extensions but closed for modifications.
What is the right way to do it? I would move those send methods (SendCPUMetric, SendRAMMetric, SendHDDMetric) to corresponding classes (SendCPUMetric method to CPUMetric class, SendRAMMEtric to RAMMetric, etc) but how to modfy SendingMetrics class so it is closed for modifications and if I need to add new metric to not change that class.
In object oriented languages like C# the Open Closed Principle (OCP) is usually achieved by using the concept of polymorphism. That is that objects of the same kind react different to one and the same message. Looking at your class "SendingMetrics" it's obvious that the class works with different types of "Metrics". The good thing is that your class "SendingMetrics" talks to a all types of metrics in the same way by sending the message "getData". Hence you can introduce a new abstraction by creating an Interface "IMetric" that is implemented by the concrete types of metrics. That way you decouple your "SendingMetrics" class from the concrete metric types wich means the class does not know about the specific metric types. It only knows IMetric and treats them all in the same way wich makes it possible to add any new collaborator (type of metric) that implements the IMetric interface (open for extension) without the need to change the "SendingMetrics" class (closed for modification). This also requires that the objects of the different types of metrics are not created within the "SendingMetrics" class but e.g. by a factory or outside of the class and being injected as IMetrics.
In addition to using inheritance to enable polymorphism and achiving OCP by introducing the interface IMetric you can also use inheritance to remove redundancy. Which means you can introduce an abstract base class for all metric types that implements common behaviour that is used by all types of metrics.
Your design is almost correct. You got 3 data retriever and 1 data sender. So it's easy to add more metric (more retriever) (open for extensions) without affecting current metrics (closed for modifications), you just need a bit more refactor to reduce duplicated code.
Instead of have 3 metrics classes look very similar. Only below line is different
var currentCpuLoad = ... //logic for getting machine CPU load
You can create a generic metric like this
internal interface IGetMetric
{
int GetData();
}
internal sealed class Metric
{
private int _threshold;
private IGetMetric _getDataService;
public Metric(IGetMetric getDataService)
{
_cpuThreshold = 95;
_getDataService = getDataService;
}
public int GetValue()
{
var currentCpuLoad = _getDataService.GetData();
if(currentCpuLoad > _cpuThreshold)
{
return 1;
}
else
{
return 0;
}
}
}
Then just create 3 GetMetric classes to implement that interface. This is just 1 way to reduce the code duplication. You can also use inheritance (but I don't like inheritance). Or you can use a Func param.
UPDATED: added class to get CPU metric
internal class CPUMetricService : IGetMetric
{
public int GetData() { return ....; }
}
internal class RAMMetricService : IGetMetric
{
public int GetData() { return ....; }
}
public class AllMetrics
{
private List<Metric> _metrics = new List<Metric>()
{
new Metric(new CPUMetricService());
new Metric(new RAMMetricService());
}
public void SendMetrics()
{
_metrics.ForEach(m => ....);
}
}

Using IObservable<T> to keep track of current state

Suppose I have an object that observes an IObservable so that it's always aware of the current state of some external source. Internally my object has a method that uses that external value as part of the operation:
public class MyObject
{
public MyObject(IObservable<T> externalSource) { ... }
public void DoSomething()
{
DoSomethingWith(CurrentT);
}
}
What's the idomatic 'reactive' way of using IObservable for 'tracking current state' instead of 'responding to stream of events'.
Idea #1 is to just monitor the observable and write down values as they come in.
public class MyObject
{
private T CurrentT;
public MyObject(IObservable<T> externalSource)
{
externalSource.Subscribe((t) => { CurrentT = t; });
}
public void DoSomething()
{
DoSomethingWith(CurrentT);
}
}
And that's fine, but keeping track of the state in a class member seems very un-reactive-y.
Idea #2 is to use a BehaviorSubject
public class MyObject
{
private readonly BehaviorSubject<T> bs;
public MyObject(BehvaiorSubject<T> externalSource)
{
this.bs = externalSource
}
public void DoSomething()
{
DoSomethingWith(bs.Value);
}
}
But using subjects directly seems to be frowned upon. But at least in this case I have the ability to use a readonly field to store the behaviorsubject.
The BehaviorSubject (or ReplaySubject) does seem like it was made for this purpose, but is there some other better way here? And if I should use the subject, would it make more sense to take the subject as an injected parameter, or take the original observable and build the subject locally in the constructor?
(by the way I'm aware about the need to deal with the 1st value if the source observable hasn't fired yet. Don't get hung up on that, that's not what I'm asking about)
I'd go with a generic solution utilizing the ReactiveUI library. RUI has a standard way of mapping IObservable<T> to an INotifyPropertyChanged stateful property.
public class ObservableToINPCObject<T> : ReactiveObject, IDisposable
{
ObservableAsPropertyHelper<T> _ValueHelper;
public T Value {
get { return _ValueHelper.Value; }
}
public ObservableToINPCObject(IObservable<T> source, T initial = default(T))
{
_ValueHelper = source.ToProperty(this, p=>p.Value, initial);
}
public Dispose(){
_ValueHelper.Dispose();
}
}
ValueHelper is contains both the current state of the observable and automatically triggers the correct INPC notification when the state changes. That's quite a bit of boiler plate handled for you.
and an extension method
public static class ObservableToINPCObject {
public static ObservableToINPCObject<T> ToINPC<T>
( this IObservable<T> source, T init = default(T) )
{
return new ObservableToINPCObject(source, init);
}
}
now given an
IObservable<int> observable;
you can do
var obj = observable.ToINPC(10);
and to get the latest value
Console.WriteLine(obj.Value);
also given that Value is an INPC supporting property you can use it in databinding. I use ToProperty all the time for exposing my observables as properties for WPF databinding.
To be Rx-ish I'd suggest avoiding the second option and go with your first, but modified in one of two ways.
Either (1) make your class disposable so that you can cleanly close off the subscription to the observables or (2) make a method that lets you clean up individual observables.
(1)
public class MyObject : IDisposable
{
private T CurrentT;
private IDisposable Subscription;
public MyObject(IObservable<T> externalSource)
{
Subscription = externalSource
.Subscribe((t) => { CurrentT = t; });
}
public void Dispose()
{
Subscription.Dispose();
}
public void DoSomething()
{
DoSomethingWith(CurrentT);
}
}
(2)
public class MyObject
{
private T CurrentT;
public IDisposable Observe(IObservable<T> externalSource)
{
return externalSource
.Subscribe((t) => { CurrentT = t; });
}
public void DoSomething()
{
DoSomethingWith(CurrentT);
}
}
Both allow proper clean-up and both don't use a subject.

Can't pass data between classes

I am developing a Kinect application based on VS2012 using winform. After I tried several methods, I still couldn't pass value from one class to another class.
Basically I have three class, a public MainWindow(), public partial FaceTrackingViewer(), and public SkeletonFaceTracker(). The last class reside in FaceTrackingViewer() class.
In SkeletonFaceTracker(), I have the following:
public bool lastFaceTrackSucceeded { get; set; }
internal void OnFrameReady(KinectSensor kinectSensor, ColorImageFormat colorImageFormat, byte[] colorImage, DepthImageFormat depthImageFormat, short[] depthImage, Skeleton skeletonOfInterest)
{
// something else
if (this.faceTracker != null)
{
this.lastFaceTrackSucceeded = frame.TrackSuccessful; //where it's set to be true.
//something else
}
}
I also tried to change to first line to:
public bool lastFaceTrackSucceeded;
public bool LastFaceTrackSucceeded
{
get { return lastFaceTrackSucceeded; }
private set { lastFaceTrackSucceeded = value; }
}
I think the two are the same though.
In MainWindow(), I have:
public partial class MainWindow : Window
{
//some other irrelevant code snippets
private FaceTrackingViewer.SkeletonFaceTracker skeletonFaceTracker = new FaceTrackingViewer.SkeletonFaceTracker();
private void button_faceOnly_Click(object sender, RoutedEventArgs e)
{
bool faceTrackSucceeded = skeletonFaceTracker.lastFaceTrackSucceeded;
// if I use the second structure in SkeletonFaceTracker(), it should be:
// bool faceTrackSucceeded = skeletonFaceTracker.LastFaceTrackSucceeded;
if (faceTrackSucceeded == true )
{
//do something
}
}
}
However, the bool faceTrackSucceeded is always false, even if the lastFaceTrackSucceeded or LastFaceTrackSucceeded in SkeletonFaceTracker() is true. I am very confused and don't know where it went wrong.
Please note that all the video processing and face tracking actions occur in FaceTrackingViewer() class. I simply want to pass some parameters and structures to MainWindow().
Thank you
One thing first - I assume you are making the variable lastFaceTrackSucceeded public purely for testing purposes. The two ways of defining the property are functionally the same in your example.
The only other thing I can think of is that you are setting LastFaceTrackSucceeded true on a different instance of SkeletonFaceTracker. You haven't provided enough code for me to be sure about this, but if you have two (or more) instances then it can be easy to get them mixed up.

Prevent method execution and property and variable access/modification

I am unexperienced with Aspect-Oriented Programming. However, I've read a fair amount of PDFs and documentation available from PostSharp, and I think that I understand the gist of the paradigm. I have a pretty unique problem, and I believe AOP can be used to solve it. My predicament is as follows:
Many classes will inherit from A, which can be enabled or disabled. Consider B, which extends A. If B is disabled, I would like all method execution and property and variable access/modification to be disabled. That is, B.ExecuteMethod(); and B.Property = newValue; will have no effect if B is disabled. Furthermore, if one expects a return value, the value will be defaulted to 0 or null if B is disabled. That is, I would like to have expected default values for objects and values.
I am using the PostSharp C# library, which seems very powerful and well-developed. I believe my problem can be solved by means of AttributeInheritance. For example, A can be defined as:
[ModularAttribute(AttributeInheritance = MulticastInheritance.Multicast)]
public class A {
private bool m_enabled;
public A(){
m_enabled = true;
}
public bool Enabled() {
get {
return m_enabled;
}
set {
m_enabled = value;
}
}
}
and B can extend A. Moreover, my attribute, ModularAttribute can be defined as:
[Serializable]
public sealed class ModularAttribute : OnMethodBoundaryAspect {
public ModularAttribute() {
}
public override void OnEntry(MethodExecutionArgs args) {
// only execute code if enabled
}
}
This attribute will be applied to B because B extends A.
The root of my problem is: I need ModularAttribute to reference A's Enabled property, such that OnEntry will only execute code if Enabled is true. Since this is a class-level aspect, I cannot parameterize a wrapped version of m_enabled to ModularAttribute since it is out of scope.
Is there a way that I can tell ModularAttribute that all of its owners will implement a specific interface? If so, could ModularAttribute access the specific properties from said interface? If so, this would solve my problem.
To clarify, I would like to "tell" PostSharp: "The class that uses ModularAttribute is guaranteed to implement C. So, let ModularAttribute access whatever C defines because it's ensured to work."
C can be defined as:
public interface C {
public bool Enabled();
}
Thus, in ModularAttribute, I could do something along the lines of
if (attachedClass.Enabled == false) {
// don't execute code
} else {
// execute code
}
This problem can be perceived as authentication on the per-object level rather than the more typical per-user level. Having to add an if, else check on every Property and Method that extends A seems like a cross-cutting concern. Thus, I think AOP is a fitting choice for this problem; however, because of my inexperience with this paradigm, I might be approaching it the wrong way.
Any guidance would be much appreciated. Thanks for the help,
I'm a little concerned that this much inheritance could be a design flaw or at least a huge maintenance headache, but assuming that it's not, let's soldier on...
I don't think there's a way to do exactly what you want to do. Even if PostSharp had the ability, C# needs to know the type at compile time (before PostSharp even touches it).
I suggest that you use CompileTimeValidate to verify that the class the aspect is used on is of a certain type, and once that's in place, you can cast args.Instance to your interface type without worrying about an invalid cast exception. And if that class doesn't implement IEnabled, then you'll get a compile-time error.
Here's a quick example:
public interface IEnabled
{
bool Enabled { get; }
}
[Serializable]
public class ModularAttribute : OnMethodBoundaryAspect
{
public override bool CompileTimeValidate(System.Reflection.MethodBase method)
{
if(typeof(IEnabled).IsAssignableFrom(method.DeclaringType))
return true;
Message.Write(method, SeverityType.Error, "MYERR001", "Aspect can't be used on a class that doesn't implement IEnabled");
return false;
}
public override void OnEntry(MethodExecutionArgs args)
{
var obj = (IEnabled) args.Instance; // this will always be a safe cast
if(!obj.Enabled)
args.FlowBehavior = FlowBehavior.Return;
}
}
There's a catch though: you don't want this aspect being used on the Enabled property itself, because that would cause a stack overflow (i.e. the aspect checks the property, causing the aspect to check the property, etc). So make sure to exclude Enabled using AttributeExclude.
class Program
{
static void Main(string[] args)
{
var b = new B();
b.Enabled = false;
b.SomeMethod();
b.AnotherMethod();
}
}
public interface IEnabled
{
bool Enabled { get; }
}
[Modular(AttributeInheritance = MulticastInheritance.Multicast)]
public class A : IEnabled
{
[Modular(AttributeExclude = true)]
public bool Enabled { get; set; }
public void SomeMethod()
{
Console.WriteLine("in SomeMethod");
}
}
public class B : A
{
public void AnotherMethod()
{
Console.WriteLine("in AnotherMethod");
}
}

Return an opaque object to the caller without violating type-safety

I have a method which should return a snapshot of the current state, and another method which restores that state.
public class MachineModel
{
public Snapshot CurrentSnapshot { get; }
public void RestoreSnapshot (Snapshot saved) { /* etc */ };
}
The state Snapshot class should be completely opaque to the caller--no visible methods or properties--but its properties have to be visible within the MachineModel class. I could obviously do this by downcasting, i.e. have CurrentSnapshot return an object, and have RestoreSnapshot accept an object argument which it casts back to a Snapshot.
But forced casting like that makes me feel dirty. What's the best alternate design that allows me to be both type-safe and opaque?
Update with solution:
I wound up doing a combination of the accepted answer and the suggestion about interfaces. The Snapshot class was made a public abstract class, with a private implementation inside MachineModel:
public class MachineModel
{
public abstract class Snapshot
{
protected internal Snapshot() {}
abstract internal void Restore(MachineModel model);
}
private class SnapshotImpl : Snapshot
{
/* etc */
}
public void Restore(Snapshot state)
{
state.Restore(this);
}
}
Because the constructor and methods of Snapshot are internal, callers from outside the assembly see it as a completely opaque and cannot inherit from it. Callers within the assembly could call Snapshot.Restore rather than MachineModel.Restore, but that's not a big problem. Furthermore, in practice you could never implement Snapshot.Restore without access to MachineModel's private members, which should dissuade people from trying to do so.
Can MachineModel and Snapshot be in the same assembly, and callers in a different assembly? If so, Snapshot could be a public class but with entirely internal members.
I could obviously do this by
downcasting, i.e. have CurrentSnapshot
return an object, and have
RestoreSnapshot accept an object
argument which it casts back to a
Snapshot.
The problem is that somebody could then pass an instance of an object which is not Snapshot.
If you introduce an interface ISnapshot which exposes no methods, and only one implementation exists, you can almost ensure type-safety at the price of a downcast.
I say almost, because you can not completely prevent somebody from creating another implementation of ISnapshot and pass it, which would break. But I feel like that should provide the desired level of information hiding.
You could reverse the dependency and make Snapshot a child (nested class) of MachineModel. Then Snapshot only has a public (or internal) Restore() method which takes as a parameter an instance of MachineModel. Because Snapshot is defined as a child of MachineModel, it can see MachineModel's private fields.
To restore the state, you have two options in the example below. You can call Snapshot.RestoreState(MachineModel) or MachineModel.Restore(Snapshot)*.
public class MachineModel
{
public class Snapshot
{
int _mmPrivateField;
public Snapshot(MachineModel mm)
{
// get mm's state
_mmPrivateField = mm._privateField;
}
public void RestoreState(MachineModel mm)
{
// restore mm's state
mm._privateField = _mmPrivateField;
}
}
int _privateField;
public Snapshot CurrentSnapshot
{
get { return new Snapshot(this); }
}
public void RestoreState(Snapshot ss)
{
ss.Restore(this);
}
}
Example:
MachineModel mm1 = new MachineModel();
MachineModel.Snapshot ss = mm1.CurrentSnapshot;
MachineModel mm2 = new MachineModel();
mm2.RestoreState(ss);
* It would be neater to have Snapshot.RestoreState() as internal and put all callers outside the assembly, so the only way to do a restore is via MachineModel.RestoreState(). But you mentioned on Jon's answer that there will be callers inside the same assembly, so there isn't much point.
This is an old question, but i was looking for something very similar and I ended up here and between the information reported here and some other I came up with this solution, maybe is a little overkill, but this way the state object is fully opaque, even at the assembly level
class Program
{
static void Main(string[] args)
{
DoSomething l_Class = new DoSomething();
Console.WriteLine("Seed: {0}", l_Class.Seed);
Console.WriteLine("Saving State");
DoSomething.SomeState l_State = l_Class.Save_State();
l_Class.Regen_Seed();
Console.WriteLine("Regenerated Seed: {0}", l_Class.Seed);
Console.WriteLine("Restoring State");
l_Class.Restore_State(l_State);
Console.WriteLine("Restored Seed: {0}", l_Class.Seed);
Console.ReadKey();
}
}
class DoSomething
{
static Func<DoSomething, SomeState> g_SomeState_Ctor;
static DoSomething()
{
Type type = typeof(SomeState);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
}
Random c_Rand = new Random();
public DoSomething()
{
Seed = c_Rand.Next();
}
public SomeState Save_State()
{
return g_SomeState_Ctor(this);
}
public void Restore_State(SomeState f_State)
{
((ISomeState)f_State).Restore_State(this);
}
public void Regen_Seed()
{
Seed = c_Rand.Next();
}
public int Seed { get; private set; }
public class SomeState : ISomeState
{
static SomeState()
{
g_SomeState_Ctor = (DoSomething f_Source) => { return new SomeState(f_Source); };
}
private SomeState(DoSomething f_Source) { Seed = f_Source.Seed; }
void ISomeState.Restore_State(DoSomething f_Source)
{
f_Source.Seed = Seed;
}
int Seed { get; set; }
}
private interface ISomeState
{
void Restore_State(DoSomething f_Source);
}
}

Categories