1

Consider following piece of code:

public class Foo
{
  private float propA = 1.0f;
  public float PropA 
  {
     get { return propA; }
     set { if (value != propA) { propA = value; DoBar(); } }
  }

  private int propB = 2;
  public int PropB 
  {
     get { return propB; }
     set { if (value != propB) { propB = value; DoBar(); } }
  }

  private double propC = -1.0;
  public double PropB 
  {
     get { return propC; }
     set { if (value != propC) { propC = value; DoBar(); } }
  }

  void DoBar() 
  {  
     //...Something is going on here
  }
}

I was wondering, if someone could recommend a nicer way for creating properties in C# lang? For instance in C++ i would use MACRO for this purpose, since it will allow me not only do some action when property has changed, but also reduce the repetition of boilerplate code.

Thank you in advance.

Leonid Lazaryev
  • 326
  • 1
  • 8
  • 2
    https://github.com/Fody/PropertyChanged - then have your `OnPropertyChanged` method call `DoBar`. – mjwills Apr 30 '19 at 10:31
  • 1
    https://stackoverflow.com/a/15228000/34092 is another approach to consider (similar to @SteveTodd's idea). – mjwills Apr 30 '19 at 10:37
  • 1
    I would define an snippet for this. I have one that creates me the scaffolding for a property with change notification. I just type `mvvmprop` and done. [More info](https://www.codeproject.com/Articles/22658/Snippet-to-Generate-a-Public-Property-Private-Back) – taquion Apr 30 '19 at 10:44
  • Consider also [this](https://marketplace.visualstudio.com/items?itemName=vs-publisher-2795.SnippetDesigner) extension – taquion Apr 30 '19 at 10:48
  • After typing your snippet you would only need to set its name once (with a rule you can set private field name based on the property name), and its default value – taquion Apr 30 '19 at 10:49
  • Wow @taquion this looks really nice. Exactly what I was searching for. Thank you a lot! – Leonid Lazaryev Apr 30 '19 at 10:50
  • Happy coding =) – taquion Apr 30 '19 at 10:50
  • @Zohar Peled, what does this question has to do with `INotifyPropertyChanged` interface? _since it will allow me not only do some action when property has changed_, this does not mean that the OP is using that interface.... – taquion Apr 30 '19 at 10:55
  • @taquion I agree it's not the same question but the same solution applies to both. – Zohar Peled Apr 30 '19 at 10:56
  • and by the way @taquion if you would post your answer, I'll definitely accept it. – Leonid Lazaryev Apr 30 '19 at 10:56
  • @ZoharPeled I don't agree, `taquion` solution to the problem is way more elegant and totally unrelated to INotifyPropertyChanged theme – Leonid Lazaryev Apr 30 '19 at 10:59
  • 1
    @LeonidLazaryev doesn't matter! the important thing is that the problem is solved! =) – taquion Apr 30 '19 at 11:03
  • @LeonidLazaryev well, vote to reopen, then. I'm still not convinced I'm wrong in closing this as a duplicate - so I will not reopen it, but if 5 reopen votes or just 1 reopen vote from a c# gold badge holder will reopen it there's nothing I can do about it. – Zohar Peled Apr 30 '19 at 11:06
  • @ZoharPeled question bookmarked, in a couple of years (or more) when I am gold badge holder I will vote for reopen it =) – taquion Apr 30 '19 at 11:12
  • @ZoharPeled I've got my answer. Just wanted to accept an answer from `taquion`, other then that - I've got great solution already. – Leonid Lazaryev Apr 30 '19 at 11:12

1 Answers1

0

You could do something like this:

   public class Foo
   {
      private float propA = 1.0f;
      public float PropA
      {
         get => propA;
         set => CheckAndExecute(ref propA, value);
      }

      private int propB = 2;
      public int PropB
      {
         get => propB;
         set => CheckAndExecute(ref propB, value);
      }

      private double propC = -1.0;
      public double PropC
      {
         get => propC;
         set => CheckAndExecute(ref propC, value);
      }

      private void CheckAndExecute<T>(ref T oldVal, T newVal) where T : IEquatable<T>
      {
         if (((IEquatable<T>) oldVal).Equals(newVal)) return;
         oldVal = newVal;
         DoBar();
      }

      void DoBar()
      {
         //...Something is going on here
      }
   }

You do the repeated work in a generic.

Steve Todd
  • 1,250
  • 6
  • 13
  • This is nice in terms of the equality check and the `DoBar` - but it doesn't remove the need to create the backing fields etc. – mjwills Apr 30 '19 at 10:39
  • as @mjwills pointed out, it doesn't solve the problem of property creationbacking fields. But thank you for your opinion. – Leonid Lazaryev Apr 30 '19 at 10:42
  • I don't think you can do away with the need for backing fields. Auto properties (which don't have backing fields) lack the ability to add code to their accessors. – Steve Todd Apr 30 '19 at 10:48
  • @SteveTodd Have a read about Fody (see my earlier link). – mjwills May 01 '19 at 07:16