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.

0lukasz0
  • 3,155
  • 1
  • 24
  • 40
MoonKnight
  • 23,214
  • 40
  • 145
  • 277
  • 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). – Joel Coehoorn Dec 19 '12 at 22:49
  • What makes you think LINQ will be slower? – Joel Coehoorn Dec 19 '12 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. – Joel Coehoorn Dec 19 '12 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`. Thanks for your time. – MoonKnight Dec 20 '12 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. – Joel Coehoorn Dec 20 '12 at 20:14

2 Answers2

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");
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 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... – MoonKnight Dec 20 '12 at 10:31
  • 1
    @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` 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. – Tim Schmelter Dec 20 '12 at 10:35
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

Community
  • 1
  • 1
Evan
  • 138
  • 6