0

All, I want to create an object array foo[], where the constructor for Foo is

public Foo(string name, string discription){}

I have a database object which has a structure (not incuding stored procedures, functions or views for simplicity) like

public class Database 
{
    public string name { get; set; }
    public string filename { get; set; }
    public List<Table> tables { get; set; }

    public Database(string name, string filename)
    {
        this.name = name;
        this.filename = filename;
    }
}

protected internal class Table 
{
    public string name { get; set; }
    public List<Column> columns { get; set;}

    public Table(string name, List<Column> columns)
    {
        this.name = name;
        this.columns = columns;
    }
}

protected internal class Column
{
    public string name { get; set; }
    public string type { get; set; }

    public Column(string name, string type, int maxLength, 
                  bool isNullable)  
    {
        this.name = name;
        this.type = type;
    }
}

I would like to know the quickest way to add Column and Table information to the Foo[] object array?

Clearly I can do

List<Foo> fooList = new List<Foo>();
foreach (Table t in database.tables)
{
    fooList.Add(new Foo(t.Name, "Some Description"));
    foreach (Column c in t.columns)
        fooList.Add(new Foo(c.Name, "Some Description"));
}
Foo[] fooArr = fooList.ToArray<Foo>();

But is there a quicker way? Clearly LINQ is likely to be slower for a query that does a simalar operation, but I care allot about speed here so any advice would be appreciated. Perhaps the use of a HashSet would be the way to go as there will not be duplicate entries...

Thanks for your time.

5
  • 1
    Think about removing the setters from your List<> properties. You don't really need them (Removing the setter won't make the object read only... only the reference to the object). Commented Dec 19, 2012 at 22:49
  • What makes you think LINQ will be slower? Commented Dec 19, 2012 at 22:50
  • Finally, why do you need an array at all? Why, exactly, is a List not good enough? The answer to this question may influence suggestions for how to solve your question. Commented Dec 19, 2012 at 22:51
  • @JoelCoehoorn Thanks for the 'setters' comment, you are right. Now the others; LINQ, under the hood is basically doing loops itself. It also has overheads ascociated with building the actual loops from the fluent/query syntax. The question is, is the loop I have the best possible. The reason for the List -> array is that I am working with an external library that takes Foo[] not List<Foo>. Thanks for your time. Commented Dec 20, 2012 at 10:29
  • linq does use loops under the hood, but why are those loops any slower than the loop you write yourself? The extra overhead is born mainly by the compiler, and often what linq really does is help you write clearer code that is easier to optimize... resulting eventually in better performance. Yes, you could have written the same code without linq... but too often that doesn't happen. Also, beware the premature optimization. Commented Dec 20, 2012 at 20:14

2 Answers 2

2

I would say change your foreach loop to for loop, as discussed here In .NET, which loop runs faster, 'for' or 'foreach'? Datastructure wise, you do need mutable structure, unless you know exactly how many records you will be inserting into fooList, then you can use Array instead of list. According to the answer of the foreach vs for-loop question, assuming it's correct, for loops on List are a bit more than 2 times cheaper than foreach loops on List, and Looping on array is around 2 times cheaper than looping on List.

So 2 improvement would be:

  1. change foreach to for

  2. use linq to compute the length for the array as per @Tim Schmelter, and change List to Array

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer. Switching to a for loop is a good idea. Thanks for the link... All the best.
2

You could initialize the array with the correct size and only use it without a backing list:

int size = db.tables.Sum(t => t.columns.Count + 1);
Foo[] fooArr = new Foo[size];
int currentSize = 0;
foreach (var tbl in db.tables)
{
    fooArr[currentSize++] = new Foo(tbl.Name, "Some Discription");
    foreach(var c in tbl.columns)
        fooArr[currentSize++] = new Foo(c.Name, "Some Discription");
}

2 Comments

Thanks, this is a good idea. I suppose I will have to run test to actually see the what sort of benifits I will recive. Thanks for your time...
@Killercam: You will at least have a good chance to reduce memory consumption and a possible OutOfMemoryException. Your list has already doubled the amount of used memory. Also remember that List<T> uses a doubling algorithm; if you are feeding items via Add (without allocating all the space first) it is going to try to double the capacity always. If the list is already large(say 1 GB), the next Add that exceeds the internal capacity of the backing array would allocate 2GB.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.