2015-10-13 32 views
1

編輯以節省您閱讀整篇文章的難度 tldr:對象的字段不應該是靜態的,除非您希望該對象的所有實例對該字段具有相同的值循環創建並向ArrayList添加新對象

我試圖創建和填充Blog對象的ArrayList。我知道泛型方法做到這一點:

create ArrayList of Blogs 
loop (some condition) 
    create new Blog 
    add this Blog to AL 

然而,當我試圖將while(datareader.read())環路內這樣做,所有在ArrayList中的元素是完全一樣的博客。具體來說,我最終得到一個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; 
    } 

正如我以前說過,這樣做的結果是一個充滿指針從Kristina_Blogs表中的最後一個博客的ArrayList。我想像ArrayList allBlogs看起來像[b,b,b,... b],因此當我說b.setTitle()等時它們全部得到更新。但是,如果我創建一個新的Blog對象,情況如何呢?在每次迭代的開始?


下面是一些額外的信息,你就不用看了,但它可能清理有關問題的結構有些混亂:

  1. 博客對象有ID,標題和消息字段和他們各自的getter/setters
  2. Kristina_Blogs是代表這些博客的表,其中包含id,標題,消息列
  3. 建議聲明爲我的數據庫引擎添加標記,但找不到標記:Microsoft SQL Server管理工作室
  4. 此代碼的工作完美,當我用字符串,而不是博客

編輯的ArrayList:包括來自博客類的代碼

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; } 

} 
+1

不回答你的問題,但考慮使用列表而不是ArrayList。 ArrayList是泛型和類型集合之前的選擇(從.Net 2開始,如果我沒有錯的話) –

+2

最好分享你的Blog代碼。我想問題是你的Blog類有靜態成員變量。 –

+0

此外它最好使用屬性來設置值,而不是'setX'和'setY' –

回答

2

您所遇到的主要問題,正如我在評論中提到的那樣,您的成員變量是靜態的,所以當您設置該值時,它們會在所有實例中更改。你應該改變你的代碼是這樣的:

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,它在該召喚的所有實例之間共享。
  • 在C#中,你可以使用property獲取或設置值,你不需要setXsetY,當你得到一個屬性的值,該屬性的get代碼將執行,當你一個值賦給一個財產set部分將執行。你可以定義屬性是這樣的:

物業:

private int id; 
public int Id 
{ 
    get 
    { 
     return id; 
    } 
    set 
    { 
     id = value; 
    } 
} 

或更爲簡單:

public int Id { get; set; } 
2

所有在Blog類中的字段都是靜態的,意義它們在所有對象實例之間共享。您希望它們成爲實例字段(意思不是static),以便每個對象都有自己的每個這些值的副本。

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關鍵字,您允許對象的不同實例擁有不同的值。

現在,每次創建博客對象時,該對象的標題和消息等都將包含自己的信息。

+0

哦,好的,謝謝。我不知道爲什麼我把這些靜態放在首位,但它現在都在運作。如果我希望所有博客都鏈接到同一個應用程序,那麼我應該讓myApp字段是靜態的嗎? – Kristina

+0

當然,但如果您更改一個博客的應用程序變量,那麼它會更改所有博客。 – Sterls

0

我會做一個快速的方法,以防止引發錯誤

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); 
     } 

該號碼所在字段的記錄,並假設指數「ID」是一個整數。還要考慮在循環之外移動「Blog」對象的創建並更改值。