4

I need to store a current value of an object and its previous value. I came up with something like this:

struct TwoStepHistory<T>
{
    private T _v0;

    public T Value
    {
        get
        {
            return _v0;
        }
        set
        {
            OldValue = _v0;
            _v0 = value;
        }
    }

    public T OldValue { get; private set; }
}

But it looks so obvious and simple that I thought there must be something in BCL or elsewhere in dotnet doing the same. Don't want to reinvent a bicycle, you know. Does anyone know about a similar structure?

There were some comments whether this is usable for reference type, and here is an example, everything works, not sure why people get confused. https://dotnetfiddle.net/BSm1Pz, v2 with target object mutation: https://dotnetfiddle.net/DGkAgv

Mike Makarov
  • 1,287
  • 8
  • 17
  • 4
    Somebody probably wrote something like this before. I'm not aware of anything like that in the framework, though. Please note that if you are going to do such a thing, you better use a class and not a struct. Also, you might want to consider using a `Queue` to keep old values, that way you are not limited to only the last one. – Zohar Peled Jul 26 '18 at 11:31
  • 12
    _"But it looks so obvious and simple that I thought there must be something"_ It's the other way around, because it's so simple there is nothing in the framework. – Tim Schmelter Jul 26 '18 at 11:32
  • 1
    It's obvious and simple but probably not something with broad application, which is why you wouldn't expect a BCL class for it. Maintaining the previous value of something is of course common, but that's what local variables are for (usually). – Jeroen Mostert Jul 26 '18 at 11:33
  • @ZoharPeled I think you are right, the `Queue` would be a full-blown version of this. But same way I c an just go down to `List` :) – Mike Makarov Jul 26 '18 at 11:38
  • Also, on a slightly flippant note you could argue there *is* something in the framework for this: `ValueTuple`. `var x = (previous: 0, current: 0); x = (x.current, 1);` A dedicated class is easier to use and less prone to mistakes, of course. – Jeroen Mostert Jul 26 '18 at 11:38
  • I'd suggest you read up on why [mutable structs are evil](https://stackoverflow.com/questions/441309/why-are-mutable-structs-evil). The only reason to make this a struct is if you want to pass it to a method, change the value and not have that change effect the variable you passed to the method. – juharr Jul 26 '18 at 11:44
  • Most types are classes. Most *interesting* use of such types involves their *mutation*, not *reassignment*. Your system only works for reassignment style changes to an item – Damien_The_Unbeliever Jul 26 '18 at 11:50
  • 2
    Heres your example of where reference types sort of break this: https://dotnetfiddle.net/HOqLuq you can update the historical item because you're only storing a reference to it, not a copy. – Jamiec Jul 26 '18 at 11:58
  • 1
    To go back to the actual question, the answer is **no** – Liam Jul 26 '18 at 12:00
  • why not push the values in a `Stack`? – NoviceProgrammer Jul 26 '18 at 12:01
  • See also: [How many Microsoft employees does it take to change a lightbulb?](https://blogs.msdn.microsoft.com/ericlippert/2003/10/28/how-many-microsoft-employees-does-it-take-to-change-a-lightbulb/) – Corak Jul 26 '18 at 12:23

1 Answers1

2

No, there is nothing in the BCL to support this. It is an implementation detail better left to application developers than the base library.

A couple of notes:

  1. Structs should be immutable
  2. You might want to consider storing a copy of the old item, rather than a reference to it - which can be changed from elsewhere (see: https://dotnetfiddle.net/HOqLuq)
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • I accept the answer but as you said it is implementation details. I explained why I made it a struct in my case, and I completely fine with the fact that underlying objects are mutable. It's the same witchhunt like "don't use goto". So I disagree with your notes. – Mike Makarov Jul 26 '18 at 12:06
  • 1
    @MikeMakarov ok. The point with notes is that theyre just things you should make note of. Not instructions you must follow or anything. There are many more things wrong (IMO) with your code. such as property setters should have no side eccts other than setting that property. But you're free to write your code how you like. – Jamiec Jul 26 '18 at 12:12