10 Replies - 4501 Views - Last Post: 26 July 2011 - 12:47 PM Rate Topic: -----

#1 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

passing Structs vs passing Classes

Posted 26 July 2011 - 02:20 AM

struct Data {};

List<Data> getData() {...};
void insertData(List<Data>) {...};

main()
{
   insertData(getData());
}




so....if i had code like that. would it be better performance-wise if i made 'Data' a class instead of a struct? it seems like I would be making three copies of each struct(they would get managed, but still...): once in getData(), second in the return value of getData(), and lastly when insertData() is run, it'll make a local copy of the arguments passed to it.

never really worked with structs before. so please bear with my stupidity and bad assumptions. can I even put structs into a collection and pass them around?

This post has been edited by Sergio Tapia: 26 July 2011 - 05:41 AM


Is This A Good Question/Topic? 0
  • +

Replies To: passing Structs vs passing Classes

#2 ragingben  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 170
  • View blog
  • Posts: 637
  • Joined: 07-October 08

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 02:30 AM

I was the same, I never really used structs just classes. But I'm pretty sure structs don't get put on the heap, where as classes get a reference on the stack and the object on the heap. So if you are using many many structs at the same time the garbage collector will have loads less work to do (as opposed to using classes) because you are just placing values on the stack, and it wouldn't have to clean up the heap.

I use then in situations where I'm processing lots of small and generally simple data structures.
Was This Post Helpful? 0
  • +
  • -

#3 CodingSup3rnatur@l-360  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 982
  • View blog
  • Posts: 969
  • Joined: 30-September 10

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 04:49 AM

Structs can get allocated on the heap if they are wrapped in a reference type though :)

The way I see it, in a language like C#, there are only two real reasons to use structs:

1) When you specifically want copy by value semantics for whatever reason, and you thus want an immutable data structure that behaves like built in .NET types.

Structs get copied by value, when passing them around methods, for example. All the data in them gets copied. Where as with reference types, only the reference is copied. This is one of the reasons why structs should be no larger than 16 bytes in size, I imagine.

2) Possibly when doing interop with API's written in C (or C++) like the WIN32 API, for example, to match with the struct data structure used in those languages.


In the majority of situations, classes are what you should use in C# :)

This post has been edited by CodingSup3rnatur@l-360: 26 July 2011 - 08:47 AM

Was This Post Helpful? 2
  • +
  • -

#4 Momerath  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 994
  • View blog
  • Posts: 2,382
  • Joined: 04-October 09

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 06:16 AM

View PostThe Architect 2.0, on 26 July 2011 - 02:20 AM, said:

so....if i had code like that. would it be better performance-wise if i made 'Data' a class instead of a struct? it seems like I would be making three copies of each struct(they would get managed, but still...): once in getData(), second in the return value of getData(), and lastly when insertData() is run, it'll make a local copy of the arguments passed to it.

never really worked with structs before. so please bear with my stupidity and bad assumptions. can I even put structs into a collection and pass them around?

You aren't passing around a struct in your sample code, you are passing around a reference to a List<T>, so it would make no difference if you turned the Data struct into a class.
Was This Post Helpful? 0
  • +
  • -

#5 Jeff H  Icon User is offline

  • D.I.C Regular

Reputation: 112
  • View blog
  • Posts: 307
  • Joined: 30-January 11

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 07:48 AM

Just a to add
If the struct contains a reference type then you get a 'Shallow copy'

For example:
If one of the fields in the struct is a class and another is a value type then
Then value type will be a copy and the other will still point to the same reference.
Was This Post Helpful? 0
  • +
  • -

#6 Momerath  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 994
  • View blog
  • Posts: 2,382
  • Joined: 04-October 09

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 08:27 AM

And to add even more info, just because: Allocating structs is about 4 times faster than allocating a class (for my simple test of a struct/class that contained one field, an int).
Was This Post Helpful? 0
  • +
  • -

#7 ragingben  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 170
  • View blog
  • Posts: 637
  • Joined: 07-October 08

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 08:36 AM

And I'm fairly certain this is because no heap is allocated for your struct with one int field, which can be significant when you are dealing with large numbers of structs. This is one reason why Point, Vector, and other data structures that are vital to the UI, and very likely to be used heavily in UI situations are all represented by structs. The additional overhead could become overwhelming in some situations if these were classes.
Was This Post Helpful? 0
  • +
  • -

#8 Jeff H  Icon User is offline

  • D.I.C Regular

Reputation: 112
  • View blog
  • Posts: 307
  • Joined: 30-January 11

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 08:49 AM

There are many or almost all references I have read say structs are allocated on the stack, but one guy explains as this

Quote

in the Microsoft implementation of C# on the desktop CLR, value types are stored on the stack when the value is a local variable or temporary that is not a closed-over local variable of a lambda or anonymous method, and the method body is not an iterator block, and the jitter chooses to not enregister the value


http://blogs.msdn.co...alue-types.aspx
Was This Post Helpful? 0
  • +
  • -

#9 CodingSup3rnatur@l-360  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 982
  • View blog
  • Posts: 969
  • Joined: 30-September 10

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 09:33 AM

Yes that basically boils down to what I said earlier. Structs go on the heap if they are direclty wrapped in a reference type (are instance fields in a class).


This:

Quote

value types are stored on the stack when the value is a local variable or temporary that is not a closed-over local variable of a lambda or anonymous method


is refering to the concept known as closures.

For example:

public void ClosureExample()
{
       int i = 10;
       Action f = () =>
       {
           Console.WriteLine(i);
       };

       f.Invoke();
}



I have access to 'i' from within the lambda. This seems obvious as we do it everyday, but if you think about it, it should seem 'wrong'. The lambda represents a method, so being able to access the variable 'i', which is outside of the method/lambda, is strange, as it is out of scope. So, how does this work?

Well, the compiler creates a nested class behind the scenes that contains that lambda as a method, and the variable 'i' as an instance field of the class. Thus, 'i' becomes a field in a reference type, and so is allocated on the heap.

The quote above was saying that when the above is NOT the case, the local struct is allocated on the stack, which is correct.

For specific details on this, see here.

This:

Quote

...the method body is not an iterator block


is much the same thing.

Here is an example of a method with an iterator block as its body:

public IEnumerable<int> IteratorExample()
{
        foreach (int i in Enumerable.Range(0, 101))
        {
            yield return i;
        }
}



In iterator blocks, you 'yield' each value to the caller. Therefore, there has to be some state machine behind the scenes to keep track of where we are in the iteration process, and the various values held within the variables. This state machine is implemented as a class, hence any local struct variables, like 'i' in the above example, will fields of a reference type, and so will be allocated on the heap :)

Here is a brilliant article on iterator blocks.

This:

Quote

...and the jitter chooses to not enregister the value


is just saying that the compiler may decide it is appropriate to place the struct in a CPU register rather than main memory. This is totally implementation defined though, and we have know real way of saying conclusively if this will happen for any given struct variable.

On Intel (x86) architectures, we have various general purpose registers depending on which specific implementation we are talking about (AX, BX, CX, DX are 16 bit registers; EAX, EBX, ECX, EDX are 32 bit general purpose registers with the lower order 16 bits being made up by the previously mentioned 16 -bit registers. There are even 64 bit extended general purpose registers (RAX, RBX, RCX, RDX) on certain implementations.

These general purpose registers (along with some other specialised registers also presumably) are technically up for grabs by the compiler if it deems it's an appropriate optimisation :)

Here is the Wiki entry on CPU registers in general.

This post has been edited by CodingSup3rnatur@l-360: 26 July 2011 - 12:23 PM

Was This Post Helpful? 3
  • +
  • -

#10 The Architect 2.0  Icon User is offline

  • D.I.C Regular

Reputation: 37
  • View blog
  • Posts: 351
  • Joined: 22-May 08

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 11:32 AM

okay...not going to quote specific posts here because they are all very long(thanks guys!) and i lost you guys like at the halfway mark.

so, when i add a struct(declared and defined in the method) to a collection, am i making ANOTHER copy of the struct on the heap?

so when the collection is returned, it contains a reference to the struct defined on the heap? while the one on the stack is destroyed?

maybe i should make this simpler:

the struct will contain a whole bunch of strings and a List<> of another type of struct(containing more strings).

should i make it a class or keep it a struct? ps, what i'm doing is passing some data from a Model class representing a web api to a Model class for a local SQL database.


ps, are there any rules saying that a class can't create a read-only property that callers get their data from instead of calling some sort of get()? when the caller wants to refresh the data, they can call refreshData(). Although this seems like a synchronization disaster waiting to happen/

This post has been edited by The Architect 2.0: 26 July 2011 - 11:41 AM

Was This Post Helpful? 0
  • +
  • -

#11 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4309
  • View blog
  • Posts: 7,460
  • Joined: 08-June 10

Re: passing Structs vs passing Classes

Posted 26 July 2011 - 12:47 PM

Make it a class. As others have said, there's almost no reason to make a struct unless you want very specific behavior (which you don't need).
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1