ArgumentNullException的问题

时间:2015-03-12 15:03:04

标签: c# asp.net nullreferenceexception

我在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;

但我认为这不是正确的做法。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:0)

您必须在每次回发时初始化所有变量,因为所有变量(和控件)都放置在页面生命周期的末尾,因此在呈现并发送给客户端之后。

所以替换

 if (!IsPostBack)
    myList = new List<Foo>();

myList = new List<Foo>();

您也不应该在ASP.NET中使用static字段,因为它们是对所有请求共享的。这意味着每个用户都有相同的列表。

如果您希望在回发后保留列表,可以使用Session。但我建议不要这样做。为什么需要将它存储在服务器内存中呢?如果您需要将DataSource用作RepeaterGridView等网络数据绑定控件,则无需存储它。只需让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

你需要保持自己的状态。有多种方法可以实现,Sessionprotected 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代替ViewStateSession的优点是它将在客户端以页面方式维护,并且在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}}

您可能会看到:ASP.NET State Management Recommendations