2

So, in some C# code, I have something similar to the two properties:

private string _foo;
private string _bar;

public Foo
{
   get;
   set {
      _foo = value;
      Bar = _foo.Substring(3, 5);
   }
}

public Bar
{
   get;
   set {
      _bar = value;
      Foo = "XXX" + _bar;
   }
}

Question: Are C# properties subject to circular references/updates, like this example would seem to cause?

Andrew Gray
  • 3,756
  • 3
  • 39
  • 75
  • did you try this in a Console app and checkout? – Dhawalk Feb 12 '13 at 21:57
  • Well, do you see an infinite loop when you run your program? – Philip Hanson Feb 12 '13 at 21:57
  • 1
    @PhilipHanson Maybe it's still running? :-) – LarsTech Feb 12 '13 at 21:58
  • No; I have a problem where I was thinking of having two (related) properties...in fact, where one property is a subset of the other's information as above! This is more of a conceptual problem at present than a concrete implementation. – Andrew Gray Feb 12 '13 at 21:58
  • 2
    If you would replace Bar = _foo.Substring(3, 5) to _bar = _foo.Substring(3, 5) or _bar = value.Substring(3, 5) should work without infinite loop – Evaldas Dzimanavicius Feb 12 '13 at 22:00
  • I would create a class with two properties and use an appropriate constructor. So instead of holding both strings here, i would encapsulate them in a separate class and hide this complexity. – Tim Schmelter Feb 12 '13 at 22:02
  • @TimSchmelter: problem with that is, the 'actual implementation' that I'm anguishing about is part of an MVC app, and one of the properties has a text field in the appropriate view. If this class were being encountered purely in code, I would do just that...of course, if I were doing that, the fields would be `private readonly _foo, _bar`, with only getters. – Andrew Gray Feb 12 '13 at 22:03

4 Answers4

3

You can avoid the infinite loop by updating the hidden field directly, like this:

private string _foo;
private string _bar;

public string Foo
{
   get { return _foo; }
   set {
      _foo = value;
      _bar = _foo.Substring(3, 5);
   }
}

public string Bar
{
   get { return _bar; }
   set {
      _bar = value;
      _foo = "XXX" + _bar;
   }
}

This will bypass the other property's setter, which eliminates the loop.

But... this generally causes maintenance headaches later on. Personally, I'd try to find an alternative design.

Philip Hanson
  • 1,847
  • 2
  • 15
  • 24
  • I heartily agree on the alternate design; part of the problem is the fact that one of my properties is a fragment of the other, yet due to some other part of our system, updating the fragment can (and should, for integrity purposes) be used to update the superset. **Lesson for Me**: prop-prop updating is not the correct tool for this job. – Andrew Gray Feb 12 '13 at 22:07
  • 1
    What about updating the fragment through a separate method, but allowing it to be accessed through a read-only property? Not sure if that is possible with your setup. Is it a requirement to update via property? – Philip Hanson Feb 12 '13 at 22:13
  • It is not a requirement to update via property. :) I'll use that tactic with this bit of code. Thanks for the great advice! – Andrew Gray Feb 12 '13 at 22:15
  • There _was_ a design problem in my snippet. Where I had two properties that updated each other, each with their own hidden field, what I really only needed was one hidden field that each property updates in its own way. The fragment's setter just pads the front of the data with stuff that fulfills the formatting; the full setter performs a full value set. The getters just return what they need to (either, the fragment or the full value.) – Andrew Gray Feb 13 '13 at 14:12
2

Are C# properties subject to circular references/updates, like this example would seem to cause?

Yes. You have a nice, infinite loop here.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • accepted Philip Hanson 's answer, even though you provided the direct answer. Reason: he added an implementation that would circumvent the issue, though the design in question is suboptimal. – Andrew Gray Feb 12 '13 at 22:12
1

Properties in C# are simple methods (getter and setter). You call one method from other method and vice versa. Result is completely expected.

Would this surprise you?

public void set_Foo(string value)
{
   set_Bar(value.Substring(3, 5));
}

public void set_Bar(string value)
{
   set_Foo("XXX" + value);
}

Call set_Foo("XXX12345") and.. you'll see the name of this site

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • I knew the get/sets were actually methods beneath the hood...wasn't sure if there was some terminating factor *also* hiding under the hood that would prevent my seeing Stack Overflow. Now, I know that answers is a resounding **No**. – Andrew Gray Feb 12 '13 at 22:13
  • @AndrewGray exactly, compiler simply generates methods with names `get_` and `set_` and method body equal to property body. Nothing more – Sergey Berezovskiy Feb 12 '13 at 22:16
1

To avoid the infinite loop, here's an alternative to Philip Hanson's answer: run the setter lines only when the value actually changes. Be nice; this is my first post/answer

private string _foo;
private string _bar;

public Foo
{
   get;
   set {
      if (_foo != value)
      {
         _foo = value;
         Bar = _foo.Substring(3, 5);
      }
   }
}

public Bar
{
   get;
   set {
      if (_bar != value)
      {
         _bar = value;
         Foo = "XXX" + _bar;
      }
   }
}
Vanlalhriata
  • 559
  • 5
  • 19