编辑以避免阅读整篇文章 tldr:除非您希望该对象的所有实例具有该字段的相同值,否则对象的字段不应该是静态的
我正在尝试创建并填充Blog对象的ArrayList。我确实知道这样做的通用方法:
create ArrayList of Blogs
loop (some condition)
create new Blog
add this Blog to AL
但是,当我尝试在while(datareader.read())
循环中执行此操作时,ArrayList中的所有元素都是完全相同的Blog。具体来说,我最终得到一个ArrayList,其中包含指向数据库表中最后一个Blog对象的多个指针。这是我的代码:
public static ArrayList AllBlogs()
{
SqlDataReader dr = anonPage.ExecuteReader("SELECT * FROM Kristina_Blogs");
ArrayList allBlogs = new ArrayList();
if (dr.HasRows)
{
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setTitle(dr["title"].ToString());
b.setMessage(dr["message"].ToString());
b.setId(dr["id"]);
allBlogs.Add(b);
}
}
dr.Close();
return allBlogs;
}
正如我之前所说,结果是一个ArrayList,其中包含指向Kristina_Blogs表中最后一篇博客的指针。我想ArrayList allBlogs看起来像[b,b,b,... b],因此当我说b.setTitle()等时它们都会更新。但是如果我创建一个新的Blog对象,情况怎么样呢?在每次迭代开始时?
以下是一些您不必阅读的额外信息,但可能会对问题的结构产生一些疑惑:
编辑:包含来自Blog类的代码
public class Blog
{
public App myApp;
public static string Title;
public static string Message;
public static int Id;
//constructors
public Blog() { }
public Blog(App App) { this.myApp = App; }
//all getters and setters look like this
public string getTitle() { return Title; }
public void setTitle(string t) { Title = t; }
}
答案 0 :(得分:3)
正如我在评论中提到的,您遇到的主要问题是您的成员变量是静态的,因此当您设置值时,它们会在所有实例中发生变化。你应该这样改变你的代码:
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string Message { get; set; }
}
以这种方式填写您的列表,不要忘记添加using System.Linq;
:
var result = new List<Blog>();
var connection = @"your connection string";
var command = "SELECT * FROM Kristina_Blogs";
var adapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
var dataTable = new DataTable();
//Get data
adapter.Fill(dataTable);
dataTable.Rows.Cast<DataRow>().ToList()
.ForEach(row =>
{
var b = new Blog();
b.Id = row.Field<int>("Id");
b.Title = row.Field<string>("Title");
b.Message = row.Field<string>("Message");
result.Add(b);
});
return result;
注意:
static
时,它将在该calss的所有实例之间共享。property
来获取或设置值,当您获得某个属性的值时,您不需要setX
或setY
{ {1}}该属性的代码将执行,当您为属性赋值时,它的get
部分将执行。您可以这样定义属性:属性:
set
或更简单:
private int id;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
答案 1 :(得分:2)
Blog
类中的所有字段都是静态的,这意味着它们在所有对象实例之间共享。您希望它们是实例字段(意思不是static
),以便每个对象都有自己的每个值的副本。
答案 2 :(得分:0)
从班级中删除静态属性:
public class Blog
{
public App myApp;
public String Title;
public String Message;
public int Id;
//constructors
public Blog() { }
public Blog(App App) { this.myApp = App; }
//all getters and setters look like this
public String getTitle() { return Title; }
public String getMessage() { return Message; }
public void setTitle(String t) { Title = t; }
public void setMessage(String m) { Message = m; }
}
使用static
变量时,对象的所有实例都将在这些变量中包含相同的值。通过删除static
关键字,您允许对象的不同实例保存不同的值。
现在,每次创建博客对象时,该对象的标题和消息等都将包含自己的信息。
答案 3 :(得分:0)
我会快速制作一个方法来防止null值抛出错误
public static string GetSafeString(SqlDataReader reader, int index)
{
if (!reader.IsDBNull(index))
return reader.GetString(index);
else
return string.Empty;
}
替换此代码:
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setTitle(dr["title"].ToString());
b.setMessage(dr["message"].ToString());
b.setId(dr["id"]);
allBlogs.Add(b);
}
使用此代码:
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setId(dr.GetInt32(0));
b.setTitle(GetSafeString(dr, 1);
b.setMessage(GetSafeString(dr, 2);
allBlogs.Add(b);
}
其中number是记录中字段的索引,并假设“id”是整数。还要考虑在循环外部移动“博客”对象的创建,只需更改值。