我在ASP.NET项目的C#类顶部声明了一个List<Foo>
类型的变量。在load方法中我实例化了这个类,但是当我尝试在另一个方法中使用这个对象(已经在load方法中实例化)时它为null,给出了错误ArgumentNullException。
以下是我的表现:
public partial class Teste : System.Web.UI.Page
{
List<Foo> myList;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
myList = new List<Foo>();
}
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" }); //NullReferenceException - myList is null here!
}
}
这可能很简单,但我是网络表单的新手,所以我不知道这里发生了什么。我知道在Windows窗体中它工作得很好。 我让它工作的唯一方法就是声明为静态:
static List<Foo> myList;
但我认为这不是正确的做法。
任何帮助都将不胜感激。
答案 0 :(得分:0)
您必须在每次回发时初始化所有变量,因为所有变量(和控件)都放置在页面生命周期的末尾,因此在呈现并发送给客户端之后。
所以替换
if (!IsPostBack)
myList = new List<Foo>();
与
myList = new List<Foo>();
您也不应该在ASP.NET中使用static
字段,因为它们是对所有请求共享的。这意味着每个用户都有相同的列表。
如果您希望在回发后保留列表,可以使用Session
。但我建议不要这样做。为什么需要将它存储在服务器内存中呢?如果您需要将DataSource
用作Repeater
或GridView
等网络数据绑定控件,则无需存储它。只需让ViewState
恢复控件的状态即可。默认情况下会自动完成。
答案 1 :(得分:0)
在每个PostbBack
上,您的变量将为null。您必须提供重新生成它的方法。如果您想以简单的方式执行此操作,请使用ViewState
。
if (!IsPostBack)
{
myList = new List<Foo>();
ViewState["myList"] = myList;
}
else
{
myList = (List<Foo>)ViewState["myList"];
}
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" }); //NullReferenceException - myList is null here!
ViewState["myList"] = myList;
}
答案 2 :(得分:0)
您只能在!IsPostBack
时实例化。按钮单击事件是一个回发。您需要根据您要完成的任务重新设计逻辑。 List<Foo>
中存储了什么?如果您打算重复使用或在多个页面上使用,请考虑将对象放在会话缓存中。
答案 3 :(得分:0)
将其作为static
将无助于Null参考例外。
您需要了解if (!IsPostBack)
事件中的Page_Load
支票,并记住网络无状态。
所以在你的第一页加载时,你的列表是实例化的。接下来会发生什么,当您单击按钮时。现在它是一个回发,这将导致!IsPostBack
检查返回false
。在这里,人们会认为List
之前已经实例化过,并且不需要再次实例化。 但网络是无国籍的,因此在Page_Load
List
null
丢失了内容,并再次设置为ViewState
。
你需要保持自己的状态。有多种方法可以实现,Session
,protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
myList = new List<Foo>();
Session["myList"] = myList;
}
else
{
myList = Session["myList"] as List<Foo>;
}
}
和Cookie会浮现在脑海中。阅读它们并相应地使用。
在您的情况下,您可以这样做:
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" });
Session["myList"] = myList; //save it back in session
}
并按下按钮
ViewState
这将在回发后恢复原始列表。但请记住会话费用昂贵,因为它们是在服务器上按用户维护的。
您也可以使用Serializable
但这需要Serializable对象。
要创建课程[Serializable]
class Foo
{
public int ID { get; set;}
public string Name {get; set;}
}
,请参阅:Basic Serialization - MSDN
ViewState
然后您可以在上面的代码中使用Session
代替ViewState
。 Session
的优点是它将在客户端以页面方式维护,并且在ViewState
的情况下服务器上没有负担。因此,使用protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
myList = new List<Foo>();
ViewState["myList"] = myList;
}
else
{
myList = ViewState["myList"] as List<Foo>;
}
}
的代码就像:
protected void btnTeste_Click(object sender, EventArgs e)
{
myList.Add(new Foo { Id = 0, Name = "Nobody" });
ViewState["myList"] = myList; //save it back in session
}
并点击按钮:
{{1}}