【问题标题】:Properties that update each other相互更新的属性
【发布时间】:2013-02-12 21:55:39
【问题描述】:

所以,在一些 C# 代码中,我有类似于这两个属性的东西:

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;
   }
}

问题:C# 属性是否会受到循环引用/更新的影响,就像这个示例似乎会导致的那样?

【问题讨论】:

  • 您是否在控制台应用程序中尝试过此操作并结帐?
  • 那么,您在运行程序时是否看到了无限循环?
  • @PhilipHanson 也许它还在运行? :-)
  • 否;我有一个问题,我正在考虑拥有两个(相关)属性......事实上,其中一个属性是上述另一个信息的子集!目前,这更像是一个概念问题,而不是具体的实现。
  • 如果您将 Bar = _foo.Substring(3, 5) 替换为 _bar = _foo.Substring(3, 5) 或 _bar = value.Substring(3, 5) 应该可以在没有无限循环的情况下工作

标签: c# properties circular-reference


【解决方案1】:

您可以通过直接更新隐藏字段来避免无限循环,如下所示:

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;
   }
}

这将绕过另一个属性的设置器,从而消除循环。

但是...这通常会导致以后的维护问题。就个人而言,我会尝试寻找替代设计。

【讨论】:

  • 我衷心同意替代设计;问题的一部分是我的一个属性是另一个的片段,但是由于我们系统的其他部分,更新片段可以(并且应该,出于完整性目的)用于更新超集。 给我的教训:prop-prop 更新不是这项工作的正确工具。
  • 如何通过单独的方法更新片段,但允许通过只读属性访问它?不确定您的设置是否可行。是否需要通过属性更新?
  • 不需要通过属性进行更新。 :) 我将在这段代码中使用这种策略。谢谢你的好建议!
  • 我的 sn-p 中有 一个设计问题。我有两个相互更新的属性,每个属性都有自己的隐藏字段,我真正只需要一个隐藏字段,每个属性都以自己的方式更新。片段的设置器只是用满足格式的东西填充数据的前面; full setter 执行一个完整的值集。 getter 只返回他们需要的内容(片段或完整值。)
【解决方案2】:

C# 属性是否会受到循环引用/更新的影响,就像这个示例似乎会导致的那样?

是的。你在这里有一个很好的无限循环。

【讨论】:

  • 接受了 Philip Hanson 的回答,即使您提供了直接回答。原因:他添加了一个可以规避问题的实现,尽管有问题的设计不是最理想的。
【解决方案3】:

C# 中的属性是简单的方法(getter 和 setter)。您从另一种方法调用一种方法,反之亦然。结果完全符合预期。

这会让你感到惊讶吗?

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

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

致电set_Foo("XXX12345") 并.. 你会看到这个网站的名称

【讨论】:

  • 我知道 get/sets 实际上是引擎盖下的方法...不确定是否有一些终止因素也隐藏在引擎盖下会阻止我看到堆栈溢出。现在,我知道答案是响亮的否。
  • @AndrewGray 确切地说,编译器只生成名称为get_ 和set_ 的方法,方法体等于属性体。仅此而已
【解决方案4】:

为了避免无限循环,这里是 Philip Hanson 的答案的替代方案:仅在值实际发生变化时运行 setter 行。对人好点;这是我的第一篇文章/答案

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;
      }
   }
}

【讨论】:

    猜你喜欢
    • 2012-06-30
    • 2013-01-27
    • 2023-01-27
    • 2013-07-19
    • 2016-04-13
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 2020-04-18
    相关资源
    最近更新 更多