2013-06-24 4 views
2

Извините, если я пытаюсь правильно это сформулировать. ООП - это не мой опыт, но я очень стараюсь учиться.Создайте экземпляр объекта каждый n-й раз через цикл

Как создать экземпляр объекта, скажем, каждую третью итерацию цикла?

Внутри цикла мне нужно назначить значения объекту, но свойство назначать значение будет зависеть от результата оператора case. Как только каждое свойство объекта было назначено, мне нужно добавить этот объект в список объектов того же типа.

Если я создаю объект до ввода цикла, то мой список снова и снова содержит один и тот же результат, потому что (я читал), что список содержит только ссылку на объект, а если объект затем изменяется, так же как и список.

Если я создаю объект в цикле, то, очевидно, каждый раз я получаю новый объект только с одним из назначенных ему свойств к моменту добавления его в список. Список будет содержать разные результаты, но будет назначено только последнее свойство, так как каждый новый объект создается.

То, что я предположил, что вы могли бы сделать это, - это создать новый объект, когда все свойства имеют назначенное ему значение (или в начале, когда оно не было). Таким образом, поскольку у моего объекта есть три свойства, каждый раз через цикл, я хотел бы добавить новый объект всякий раз, когда int iCounter был равен 0, добавлял значения и увеличивал iCounter, тогда, когда iCounter равен 3, установлено значение 0. Однако, когда я пытаюсь создать объект внутри оператора if, остальная часть программы не видит, что объект существует.

Я также предположил, что я мог бы попробовать какую-то макроподстановку, которая, как я обычно, прибегает к Фоксу, я читал, что это большой нет-нет в C#.

Любые идеи?

try 
{ 
    cProducts Product = new cProducts(); 
    SqlConn2.Open(); 
    rdr2 = SqlComm2.ExecuteReader(); 
    int iScanLine = 0; 
    while (rdr2.Read()) 
    { 
     iScanLine++; 
     Product.product = rdr2["product"].ToString(); 
     Product.sOrder = rdr2["order_id"].ToString(); 
     switch (rdr2["detail"].ToString()) 
     { 
      case "Quantity": 
       Product.quantity = Convert.ToInt16(rdr2["display_value"]) ; 
       break; 
      case "Option": 
       Product.Option = rdr2["display_value"].ToString(); 
       break; 
      case "Size": 
       Product.Size = rdr2["display_value"].ToString(); 
       break; 
     } 
     if (iScanLine == 3) 
     { 
      lProducts.Add(Product); 
      thisPage.sProducts.Add(lProducts[lProducts.Count() - 1]); 
      iScanLine = 0; 
     } 

    } 
} 
+7

Оператор '%' (модуль) дает остаток от целочисленного деления. Таким образом, если 'n% 3 == 0', то n делится на 3. – spender

+2

Обратите внимание, что это фактически очень мало связано с объектно-ориентированным программированием как таковым. То, что вы действительно задаете, - «как я могу что-то делать каждые X итераций цикла»? Тот факт, что «делать что-то» в этом случае «создает экземпляр нового объекта», является полностью вспомогательным. – David

+2

Возможно, вы хотите пересмотреть SQL-запрос, возвращающий данные, чтобы исправить вашу проблему в первую очередь? Похоже, вы можете изменить запрос, чтобы вернуть одну строку за элемент. – Gene

ответ

1

Вы можете просто изменить этот бит:

if (iScanLine == 3) 
{ 
    lProducts.Add(Product); 
    thisPage.sProducts.Add(Product); //<-- We know the object just added is still in Product 
    iScanLine = 0; 
    Product = new cProducts(); //<-- Create a new object to start populating 
} 

Кроме того, я знаю, что рамки .NET является достаточно новым, будучи всего лишь десять лет назад, но вы могли бы рассмотреть чтении Naming Guidelines:

X НЕ использование венгерских обозначений.

+0

Aha! Спасибо, понял. – user2516085

0

Используйте оператор Modulus для проверки делится на ожидаемой n го значения переменной итерация или нет

if(value % 3 == 0) 
{ 
    //do stuff 
} 
value++; 
0

Вы неоднократно добавлять один и тот же Product в свой список, и никогда не создать новый. Когда вы дойдете до конца цикла, он появится так, как будто у вас есть только один элемент.

После того, как вы добавили свой товар (в пределах if (iScanLine == 3)), я подозреваю, что вы хотите создать новый элемент: Product = new cProducts().

Кроме того, я хотел бы ссылку на этот конкретный комментарий, который вы делаете в вашем вопросе:

Если я создаю объект до входа в цикл, то мой список просто содержит один и тот же результат снова и снова опять же, потому что (я читал), что список содержит только ссылку на объект, а если объект , то он изменился, также как и список.

Следующий код приведет к 5 отдельных объектов добавляются в список:

List<cProducts> list = new List<cProducts>(); 
cProducts Product = new cProducts(); 
for (int i = 0; i < 5; i++) 
{ 
    list.Add(Product); 
    Product = new cProducts(); 
} 

Вы правы, что список содержит только ссылки на объекты, - но вы не изменяете какие-либо из объекты; вы создаете новые. Это фундаментальный принцип программирования, и я бы посоветовал вам потратить время, чтобы понять, как это работает, прежде чем двигаться дальше.

+0

Спасибо, Дэн, это имеет большой смысл. Супер впечатлен скоростью реакции здесь! – user2516085

0

Не уверен, что если я полностью понимаю, но следующий цикл whould использовать счетчик, чтобы выполнить каждый третий раз

int isThirdTime = 0; //Test condition for third time equality 
while (true) //neverending loop 
{ 
    if (isThirdTime == 3)//test for 3rd time 
    { 
     // add to list 
     isThirdTime = 0; //reset counter 
    } 
    isThirdTime++; // Increase the counter 
} 
1

Похоже, у вас есть таблица с четырьмя столбцами, где каждый продукт, представленных в трех последовательных строках

product | order_id | detail | display_value 
A   X   Quantity 5 
A   X   Option  Foo 
A   X   Size  XL 
B   X   Quantity 2 
... 

И вы пытаетесь читать продукты. Я предлагаю вам сохранить текущее название продукта и сравнить его с именем последнего продукта. Если имя изменено, то вы читаете данные следующий продукт, таким образом, вы можете создать новый продукт и добавить его к списку продуктов:

IDataReader reader = SqlComm2.ExecuteReader(); 
List<Product> products = new List<Product>(); 
Product product = null; 

while (reader.Read()) 
{ 
    var name = reader["product"].ToString(); 

    if (product == null || product.Name != name) // check if new product 
    {       
     product = new Product(); // create new product      
     product.Name = name; // fill name 
     product.OrderId = reader["order_id"].ToString(); // and order 
     products.Add(product); // add to products 
    } 

    object value = reader["display_value"]; // get value from row 

    switch (reader["detail"].ToString()) 
    { 
     case "Quantity": 
      product.Quantity = Convert.ToInt16(value); 
      break; 
     case "Option": 
      product.Option = value.ToString(); 
      break; 
     case "Size": 
      product.Size = value.ToString(); 
      break; 
    }  
} 

Как вы можете видеть, я также рефакторинг именования - PascalCase для свойств , camelCase для локальных переменных, без венгерских обозначений. Также введены новые имена для свойств - Product.Name вместо нечетных Product.Product, OrderId вместо sOrder.