amirfg
amirfg

Reputation: 281

How to create a list of class in another class?

I am dealing with the following class structure:

 internal class C1
{
    private static readonly int iMinVal = 1;
    private static readonly int iMaxVal = 100;
    public readonly int Number;

    public C1(int iNum)
    {
        if (iNum < iMinVal || iNum > iMaxVal)
            throw new OverflowException();
        this.Number = iNum;
    }
}

internal partial class C2
{
    public readonly List<C1> Series = new List<C1>(10);

    public C2(List<int> lNumbers)
    {
        lNumbers.Sort();

        try
        {
            Series[0] = new C1(lNumbers[0]);
            Series[1] = new C1(lNumbers[1]);
            Series[2] = new C1(lNumbers[2]);
            Series[3] = new C1(lNumbers[3]);
            Series[4] = new C1(lNumbers[4]);
            Series[5] = new C1(lNumbers[5]);
            Series[6] = new C1(lNumbers[6]);
            Series[7] = new C1(lNumbers[7]);
            Series[8] = new C1(lNumbers[8]);
            Series[9] = new C1(lNumbers[9]);
        }
        catch (OverflowException)
        {
            MessageBox.Show("M1!","M2");
            throw;
        }
    }

I try to use these two classes in the following way:

private void btn_Click(object sender, EventArgs e)
    {
        List<C2> lRes = new List<C2>(5);
        for (int iRow = 0; iRow < 5; iRow++)
        {
            List<int> lNumbers = new List<int> {6, 2, 5, 3, 1, 4, 10, 8, 7, 9};
            lRes[iRow] = new C2(lNumbers);
        }
    }

But it does not work. The error message says:

System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection.

I will be very appreciated if anybody could help me to find my mistake.

Upvotes: 0

Views: 97

Answers (5)

thepaoloboi
thepaoloboi

Reputation: 878

The C1 class will store an integer number, no issue on that.

The C2 class will store a List of C1 objects. It is instantiated on declaration, giving it the size of 10. Be careful: it is still empty, no matter the size you set.

So, the dirty filling on C2 constructor, will correctly raise the exception. See the working code:

Series.Add(new C1(lnumber[0]));
...
Series.Add(new C1(lnumber[9]));

As suggested by Dmitry, it would be much better to use the Linq approach.

On btn_Click method, you are making the same mistake. The lRes List is correctly initialized and sized, but still empty. So, you have to apply the same fix seen before:

lRes.Add(new C2(lNumbers);

Upvotes: 1

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

Well, line

 public readonly List<C1> Series = new List<C1>(10);

means "Create list with 0 items, but reserve space for 10 items (in order to not reallocating memory)". Please, note that Series doesn't have any items, and that's why

 Series[0] = new C1(lNumbers[0]);

will throw exception (Series[0] doesn't exist since 0 is out of range). You should Add items, e.g. quick (and dirty) patch

  public C2(List<int> lNumbers) {
    lNumbers.Sort();

    try
    {
        Series.Clear();

        Series.Add(new C1(lNumbers[0])));
        Series.Add(new C1(lNumbers[1]));
        Series.Add(new C1(lNumbers[2]));
        Series.Add(new C1(lNumbers[3]));
        Series.Add(new C1(lNumbers[4]));
        Series.Add(new C1(lNumbers[5]));
    }
    catch (OverflowException)
    {
        MessageBox.Show("M1!","M2");
        throw;
    }
}

a better approach is Linq:

// IEnumerable<int> - let's generalize: what if we want to pass an array?
public C2(IEnumerable<int> lNumbers) {
  // public method arguments validation
  if (null == lNumbers)  
    throw new ArgumentNullException(nameof(lNumbers));

  try {
    Series = lNumbers
      .OrderBy(item => item) 
      //.Take(10) // uncomment, if you want to take just top 10 items, not more
      .Select(item => new C1(item))
      .ToList();
  }
  catch (OverflowException) {
    MessageBox.Show("M1!","M2");
    throw;
  } 
}  

Upvotes: 2

LiefLayer
LiefLayer

Reputation: 1073

You code is confusing (at least for me). But the first thing I would change is the way you "add" elements to your list. You should use the Add method to add elements to your list. Also there is no reason to create a new List lNumbers each for iteraction.

Upvotes: 1

Bad Dub
Bad Dub

Reputation: 1593

Is it because you are doing Row < 5 but there are 6 of these lines Series[0] = new C1(lNumbers[0]);

So is the Series[5] = new C1(lNumbers[5]); outside the index causing that error?

EDIT: Also this line is incorrect in OP.

List<**C2**> lRes = new List<**C1**>(5);

Upvotes: 1

frankiehf
frankiehf

Reputation: 180

Series is a list of C1 items, i would use Series.Add() instead on Series[0],[1] etc, or youre basically using a list as if it was an array

Upvotes: 1

Related Questions