0

With all the knowledge I possess at this very moment I cannot decide which shall I use for my use case.

This is now example with struct.

The first class looks like this:

class Owner
{
  public A[] Kids;

  public Owner(int count)
  {
    Kids = new A [count];

    // If I would use classes I would need to create new class for each item, right?
    // It would look like below and my worries are memory impacts because of new A()
    // for(int i = 0; i < count; Kids[i++] = new A());
  }
}

The second class looks like this:

class Node
{
  private Owner o;
  private int num;
  private A[] kids;

  public Node(Owner o, int num)
  {
   this.o = o;
   this.num = num;
  }

  public A[] Kids
  {
    get
    {
      this.kids = o.Kids[num].NextList;
      return this.kids;
    }
  }
}

The type A looks like this

<struct or class> A
{
  public int Value;
  public A[] NextList;
}

The question is now when using structs would the access run faster than when using classes?

Would I get memory overhead when using classes since I would need to initalize each class.

Would I need to take care of killing references when using classes?

Which would you use guys in this case?

I apologize in case this is a duplicate or if i did something wrong. Please tell me what I did wrong before downgrading the question. I am still new to this forum.

dev hedgehog
  • 8,698
  • 3
  • 28
  • 55
  • Is `A` ever mutated, or is it used in an immutable fashion? Regarding your question on references, all you need to do is "let go" of them in order for them to be eligible for garbage collection. I tend to find classes are more than adequate even in situations where structs might be slightly better. I have fewer and fewer reasons these days to bother with `struct` stuff. – Adam Houldsworth Sep 27 '13 at 11:05
  • 3
    I think you are overestimating the impact of using classes. I would suggest you pick the one that makes most sense and only deal with performance issues as they arise. As Donald Knuth once said "Premature optimization is the root of all evil". If you really are that concerned about optimizing this, I would profile it. Test both scenario's and measure the time. – Moeri Sep 27 '13 at 11:05
  • There are lots of debates about the advantages of using classes or structs, I was downvoted a few days ago for suggesting the use of a struct so I can understand your nervousness. I think the answer is going to be something along the lines of 'it depends', and on many factors. I generally use classes now but I suspect the actual difference is negligible. – SteveB Sep 27 '13 at 11:06
  • 7
    Default: If you can't decide between a class and a struct, then use a class. – Matthew Watson Sep 27 '13 at 11:06
  • @bhs It tends to be opinionated and is almost entirely dependent on how you intend to use the type. – Adam Houldsworth Sep 27 '13 at 11:06
  • If your question is regarding classes vs. structs, there's plenty of duplicate questions: http://stackoverflow.com/questions/7484735/c-struct-vs-class-faster http://stackoverflow.com/questions/608392/struct-vs-class-for-long-lived-objects – Adam Kewley Sep 27 '13 at 11:07
  • @AdamHouldsworth A.Value is being set. The NextList presents next node and so on. – dev hedgehog Sep 27 '13 at 11:07
  • Whichever you choose, I'd advise you *not* to have public fields... – Jon Skeet Sep 27 '13 at 11:07
  • 1
    @devhedgehog Another piece of advice often expressed is making `struct` types immutable. I tend to follow this also. Stick with a class in this instance. Yes there is "overhead" with a class, reference space required and GC concerns, but the CLR is optimized for those tasks - those are bread and butter tasks of the CLR (it does them very well). – Adam Houldsworth Sep 27 '13 at 11:09
  • @JonSkeet I just type that down fast for you guys to get an idea of what I am doing. Its kinda tree. The fields wont be public :) – dev hedgehog Sep 27 '13 at 11:11
  • JonSkeet save my day :) Which one would you pick in this case? – dev hedgehog Sep 27 '13 at 11:59
  • I "default" to using classes - I very rarely go for structs, to be honest. Outside my Noda Time project, I can't remember the last time I wrote a custom struct. – Jon Skeet Sep 27 '13 at 12:04
  • But in my A struct I have an array and that is reference. Does that mean the array's items are references and if I change an in Owner class I wouldn't lose that information in Node class? Node.A holds Owner.A in my example. – dev hedgehog Sep 27 '13 at 12:10

1 Answers1

1

TL;DR: Use a class.

Since you are using an array and you are worried about memory, there is one thing to bear in mind:

If you have an array of structs, then the total bytes allocated for the array will be sizeof(your struct) * number of elements

If you have an array of classes, then the total bytes allocated for the array will be sizeof(reference) * number of elements (where the size of a reference is 32 bits for x86 and 64 bits for x64).

This could make a big difference in some cases.

If the total size of an array exceeds 85,000 bytes then it will be placed onto the Large Object Heap. Otherwise, it goes on the normal heap. It could mean that using a struct will cause some of your arrays to exceed the 85,000 byte threshold, while they would not reach that threshold if you used a class instead.

Items on the Large Object Heap are not compacted during Garbage Collection (*), so you can get problems with memory fragmentation if you have too many large objects.

Note that this also applies to many other collections (such as List<T>), because they use an array in their implementation.

The overhead of using a class instead of a struct is pretty negligible in most cases, and in any case you should instrument the code to be sure, if you think it is causing an issue.

Therefore, you should generally just use a class.

There is another thing to be aware of:

If you have a List of structs, you cannot change the properties of individual elements in the List without replacing the entire element with an updated one.

So this isn't possible:

List<MyStruct> list = new List<MyStruct>();
... init list
list[0].Value = 1; // Compile error for structs, no error for classes.

This shouldn't be an issue though - because your structs are always immutable so you wouldn't try to do that in the first place, right? ;)


(*) This isn't strictly true any more. .Net 4.51 introduces a way of allowing the next garbage collection to move large objects, but this has to be programmatically instigated.

http://blogs.msdn.com/b/mariohewardt/archive/2013/06/26/no-more-memory-fragmentation-on-the-large-object-heap.aspx

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • I dont have list of structs just arrays. As you can see in my example given the Node class holds Kids. If I make that a struct I wouldnt care about releasing reference, right?. Would the access run faster to Node.Kids if I pick structs? – dev hedgehog Sep 27 '13 at 11:21
  • @devhedgehog You don't care about "releasing reference" for classes either. When you cannot reach an object from anywhere, it automatically becomes eligible for garbage collection. – Matthew Watson Sep 27 '13 at 11:35
  • @downvoter: Please explain what is wrong; otherwise the downvote is pretty meaningless. – Matthew Watson Sep 27 '13 at 11:45
  • When I dont need owner in node I need to set owner to null. Else the node will always stay there because owner is the main class. No matter if I dont use the node anymore it will stay there. As far I understood GC. Take a look at my example. I am holding instance of Owner in Node. I should release the instance when the Node is not needed anymore right? – dev hedgehog Sep 27 '13 at 11:46
  • @devhedgehog Yes, but I thought you were talking about the type called `A` - that's the one you were thinking about making a struct, right? `Owner` is already a class type. – Matthew Watson Sep 27 '13 at 11:50
  • I am talking about the type A too. If A is clsas and I store instance of Owner.A in Node.A I would still need to kill Node.A. So the complete Node may get collected since Node.A will keep holding Owner.A for ages. – dev hedgehog Sep 27 '13 at 11:54
  • @devhedgehog Yes, you will need to null out the node - but you need to do that to keep the data structure correct; the garbage collection that occurs as a result of that is just a side-effect (albeit an important one). However, I think you're storing an ARRAY of `A`, which itself is a reference type regardless of whether `A` itself is a reference type. – Matthew Watson Sep 27 '13 at 12:07