处理对象时的StackOverflowException

本文关键字:StackOverflowException 对象 处理 | 更新日期: 2023-09-27 17:53:31

我已经创建了一个类来将搜索值存储到会话中。这样,当我从另一个页面返回到搜索页面时,我就可以获得存储在会话中的值。当搜索页面加载时,我从会话中获取值,填充文本字段,然后处理对象。但是当我试图处理这个物体时,我得到一个StackOverflowException。为什么会发生这种情况,我该如何解决它?

    public class SearchValue : IDisposable{
          public int ID {get; set;}
          public string Name {get; set;}
          public void Dispose()
          {
              this.Dispose();
          }
     }
            public void SaveSearchValueToSession()
            {
                SearchValue searchValue = new SearchValue();
                searchValue.ID = Convert.ToInt32(txtID.Text);
                searchValue.Name = txtName.Text;
                Session["SEARCH_VALUE"] = searchValue;
            }
protected void Page_Load(object sender, EventArgs e){
      SearchValue searchValue = (SearchValue)Session["SEARCH_VALUE"];
      txtID.Text = searchValue.ID.ToString();
      txtName.Text = searchValue.Name;
      //Right here I would like to dispose the object
      searchValue.Dispose()
}

处理对象时的StackOverflowException

您正在从Dispose方法内部调用相同的方法。这确实会导致StackOverflowException。我想知道你是否真的需要实现IDisposable,如果你理解它的目的…

如果你真的需要:

  1. Dispose一个有意义的实现,释放未管理的资源等;
  2. 在变量周围使用using;
  3. 处置后不要保存在Session内。

请参阅垃圾收集基础。

从评论中我注意到你担心创建太多的对象。别担心,这里没有问题。这一点尤其正确,因为您的对象(单个)现在不会被垃圾收集:您将它保存在会话中,直到会话被销毁。你不断重复使用同一个对象

您的问题源于实现IDisposable模式的方法不正确。下面是实现它的一个简短但完整的示例:

public class ThisIsDisposable : IDisposable
{
    public ThisIsDisposable() { }
    private bool _isDisposed = false;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (!_isDisposed)
            {
                //Do your unmanaged disposing here
                _isDisposed = true;
            }
        }
    }
}

如果类是sealed,那么第二个Dispose(bool)方法应该标记为private而不是virtual。IDisposable的主要用途是处理非托管资源。如果您没有非托管资源,您仍然可以实现它,以便对象可以在using语句中使用,但通常Dispose(bool)重载在这种情况下不会做任何事情。

参见CA1063 (https://msdn.microsoft.com/en-us/library/ms244737.aspx) and IDisposable Interface (https://msdn.microsoft.com/library/system.idisposable.aspx)

正如你的评论所说,使用IDisposable不会自动释放内存。当不再有对对象的引用时,对象将被垃圾收集。存储对您的值的引用并且从不删除这些引用将导致内存泄漏,所以如果您想确保不泄漏内存,那么您需要确保对您创建的对象没有更多的活动引用(清除列表/会话对象等)。

在你的例子中,完全没有必要实现这个模式,因为你的对象不在using语句中使用,而且它们不消耗托管资源。

使用会话是一场艰苦的战斗。就我个人而言,我只使用他们的帐户登录状态。查询字符串可以帮助您解决这个问题。请看下面的例子。

页面之前

Response.Redirect("http://yoursite.com/search?id=12");

然后在搜索页面(假设)(page Load)

// usual if(!Page.PostBack)
int searchId = -1;
if(Request.QueryString.Count > 0)
{
   String searchIdStr = Request.QueryString["id"]
   if(searchIdStr != String.Empty)
   {
       try{ 
          searchId = Convert.ToInt32(searchIdStr); 
          SearchValue searchValue = searchValueRepo.GetSearchValues()
            .Find(o => o.ID == searchId);
          if(searchValue == null){
             //Failed to find your search values
          }
       } catch (Exception ex) { //failed to convert to integer };
   }
}

然后,如果你觉得用户对查询字符串有太多的控制权,你可以设置id=239847hcjdhnsjk或一个加盐的哈希值,这样就没有人可以试图改变这个值来改变网站的行为。

相关文章:
  • 没有找到相关文章