【问题标题】:I am getting into infinite loop in property setter我在属性设置器中进入无限循环
【发布时间】:2013-04-15 19:31:00
【问题描述】:
public int Position
{
    get
    {
        if (Session["Position"] != null)
        {
            Position = Convert.ToInt32(Session["Position"]);
        }
        else
        {
            Position = 5;
        }
        return Position;
    }
    set
    {
        Position = value;
    }
}

我的程序调用 get 并进入 if 循环,然后无限运行到 set 代码中

【问题讨论】:

  • @Knaģis 有更正的代码,但要进一步解释原因:将这些 getter 和 setter 视为函数,因为它们在幕后。如果一个函数在内部调用自己,而没有退出的方法,那么您将处于无限循环中。

标签: c# asp.net properties setter


【解决方案1】:

错误是因为在您的 set {} 中您递归地调用了相同的设置器。

正确的代码是

private int _position;
public int Position
{
    get
    {
        if (Session["Position"] != null)
        {
            this._position = Convert.ToInt32(Session["Position"]);
        }
        else
        {
            this._position = 5;
        }
        return this._position;
    }
    set
    {
        this._position = value;
    }
}

【讨论】:

  • 您实际上并不需要同时使用下划线和this。大多数人会发现下划线表示您指的是本地成员,没有什么需要消除歧义。
  • 下划线对我(和许多其他人)来说实际上只是一个习惯问题,但在我看来(还有 StyleCop stackoverflow.com/questions/1562540/…this 应该始终是强制性的。
  • 是的,StyleCop 错了。 :) 堆栈溢出问题有dissenting opinions
【解决方案2】:

使用成员变量或者将其存储在会话中。

private int _position;
public int Position
{
    get
    {
        if (Session["Position"] != null)
        {
            _position= Convert.ToInt32(Session["Position"]);
        }
        else
        {
            _position= 5;
        }
        return _position;
    }
    set
    {
        _position = value;
    }
}

【讨论】:

    【解决方案3】:

    会话状态项没有什么特别像字符串的。

    你为什么不按照 KISS 原则做类似的事情

    public int Position
    {
      get { return (int) ( Session["Position"] ?? 5 ) ; }
      set { Session["Position"] = value ;               }
    }
    

    或(取决于您的实际要求/规格:

    public int Position
    {
      get { return Session["Pointer"] as int? ?? position ?? 5 ; }
      set { position = value ; }
    }
    private int? position ; // backing store
    

    【讨论】:

    • 作为int? int是值类型,怎么可能是as
    • @KenKin: int?Nullable<int> 的语法糖,这是一种引用类型(并且是特殊的,引导)。直接int 将在会话存储中被装箱; int? 用于所有意图和目的,已经装箱。请参阅规范,ISO 23270 § 14.9.11:as 运算符用于将值显式转换为给定的引用类型或可空类型...当转换为可空类型时,as 运算符使用包装转换,拆箱转换或空类型转换(第 13.7.1 节)...如果指示的转换不可行,则结果值为空。
    【解决方案4】:

    一个自动实现的属性属性由一个 getter、一个 setter 和一个支持字段组成。如果您自己编写代码,则可能不需要字段。

    你的getter调用setter,setter调用setter;那将是无限递归。您可能需要一个用于存储Position 的字段。

    但是,如果我们将其更改为存储到字段中,则 setter 实际上不起作用。所以,代码可以改成:

    public int Position {
        set {
        }
    
        get {
            int x;
            return (x=Convert.ToInt32(Session["Position"]))>0?x:5;
        }
    }
    

    你不需要检查 null,Convert.ToInt32(null) 是零。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多