Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Float Wrapper For Use In Observer Pattern

I am trying to implement observable native data types in C# (float, int, string, List). I should add that I am fairly new to C# and come from a C++ background.

My first thought was to have an observable interface like so:

public interface IObservable {

    void registerObserver(IObserver observer);

    void deregisterObserver(IObserver observer);

    void notifyObservers();
}

And then to create a wrapper for a native data type (for example float) that overloads the operators so it is (mostly) seamless to use:

Float f1 = new Float(0);
Float f2 = f1 + 2;

This would have to be an abstract base class since interfaces can't overload operators.

Then I wanted to create an ObservableFloat which combined both ideas but called notifyObservers on any change to its state. The class using it would see it as a Float and would have no idea it was internally also an Observable.

For this I would normally overload the assignment operator so instead of doing something like:

return new Float(f1.value + f2.value);

It would modify the first instance and return it. But since assignment seems to always change the reference, I would loose my observable and its list of observers on the first assignment operation, right?

I found this post that implements an observer using events in C#: link This code:

private State _state;

public State MyState
{
    get { return _state; }
    set
    {
        if (_state != value)
        {
            _state = value;
            Notify();
        }
    }
}

Does essentially what I want: when the State variable gets assigned a new value it does the assignment and also calls a function. Is there any way you can think of to achieve this while shielding the using class (Product in the example) from knowing that the variable is an Observable?

like image 706
aspirino67 Avatar asked Jul 17 '26 21:07

aspirino67


1 Answers

I think you should use something fluent-like for flexibility instead of overloading primitive types and their operators just to inject them somewhere it doesn't belong:

public interface INumeric
{
    INumeric Add(INumeric num);
    INumeric Sub(INumeric num);
    INumeric Mul(INumeric num);
    INumeric Div(INumeric num);   
}

So, for instance you will get something like this inside, if you want to copy primitive types behavior:

public INumeric Sub(INumeric b)
{
    var a = this;
    return new Numeric(a.Value-b.Value);//obviuously, no notify here
}

And if you want to work with instance in fluent style and notify observers:

public INumeric Sub(INumeric b)
{
    var a = this;
    a.Value = a.Value - b.Value;//notify 'a' observers or whatever here.
    return a;
}

In code it will look like this, and will not break on assignment, but beware of little trick below which can confuse you when working with references (omg it will be impossible to debug):

var a = new Numeric(10);
var b = new Numeric(2);

a = a.Sub(b)//10 - 2 = 8
     .Add(a)//8 + 8 = 16
     .Add(b);//16 + 2 = 18

And in primitive form:

a = a - b + a + b; //10 - 2 + 10 + 2 = 20

PS:

As you see, it is bad idea to overload primitive types. They just too different in nature from references which can easly shuffle your entire logic.

like image 104
eocron Avatar answered Jul 20 '26 09:07

eocron