处理对象时的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()
}
您正在从Dispose
方法内部调用相同的方法。这确实会导致StackOverflowException
。我想知道你是否真的需要实现IDisposable
,如果你理解它的目的…
如果你真的需要:
- 给
Dispose
一个有意义的实现,释放未管理的资源等; 在变量周围使用 - 处置后不要保存在
Session
内。
using
;请参阅垃圾收集基础。
从评论中我注意到你担心创建太多的对象。别担心,这里没有问题。这一点尤其正确,因为您的对象(单个)现在不会被垃圾收集:您将它保存在会话中,直到会话被销毁。你不断重复使用同一个对象
您的问题源于实现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
或一个加盐的哈希值,这样就没有人可以试图改变这个值来改变网站的行为。