我创建了一个类来将搜索值存储到会话中。这样,当我从另一个页面返回搜索页面时,我可以获得存储在会话中的值。加载搜索页面时,我从会话中获取值,填充文本字段并随后处理该对象。但是当我尝试处理对象时,我得到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()
}
答案 0 :(得分:5)
您正在Dispose
方法中调用相同的方法。这确实会导致StackOverflowException
。我想知道你是否真的需要实施IDisposable
,如果你了解它的目的......
如果你真的需要:
Dispose
,免费的非托管资源等; using
; Session
内。另请阅读Fundamentals of Garbage Collection。
从评论中我注意到你担心会创建太多的对象。别担心,这里没问题。这尤其正确,因为您的对象(单个)现在不会收集垃圾:您将其保存在会话中,直到会话被破坏为止。你一遍又一遍地重复使用同一个对象。
答案 1 :(得分:2)
您的问题源于实施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
而不是虚拟。 IDisposable
的主要用途是处置非托管资源。如果您没有非托管资源,您仍然可以实现它,以便可以在using
语句中使用该对象,但通常Dispose(bool)
重载在这种情况下不会执行任何操作。
请参阅CA1063(https://msdn.microsoft.com/en-us/library/ms244737.aspx)和IDisposable
界面(https://msdn.microsoft.com/library/system.idisposable.aspx)
正如您的评论所说,使用IDisposable
不会自动释放内存。当没有对该对象的引用时,您的对象将被垃圾收集。存储对您的值的引用并且永远不会删除这些引用会导致内存泄漏,因此如果您想确保不泄漏内存,那么您需要确保没有更多对这些引用的活动引用你创建(清除列表/会话对象等)。
在您的情况下,完全没有必要实现此模式,因为您的对象未在using
语句中使用,并且它们不会消耗托管资源。
答案 2 :(得分:0)
使用会话是一场艰苦的战斗。就个人而言,我只是将它们用于帐户登录状态。查询字符串可以帮助您。请参阅下面的示例。
之前的页面
Response.Redirect("http://yoursite.com/search?id=12");
然后在搜索页面上(假设)(页面加载)
// 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
或盐渍哈希,这样就没有人可以尝试更改该值来更改网站的行为。< / p>