maxp
maxp

Reputation: 25141

Storing reference types in Struct

Say I had a very simple struct in c#

   public struct foo{
   public  int a{get;set;}
   public  int b{get;set;}
   public  int c{get;set;}
   public  int d{get;set;}
   public  string hello {get;set;}
   }

I take it the above is more 'efficient' than using a class?

At what point, if I continued to add string properties, would it be time to convert the struct to a class?

Edit: I had planned to pass this struct around a GDI - centric application. I had always assumed structs were more performant when dealing with mainly value types.

Upvotes: 8

Views: 6471

Answers (5)

supercat
supercat

Reputation: 81149

If someone says:

  foo x[100];
  foo[1] = foo[2];
  foo[1].a += 5;

should the latter statement affect foo[2].a? If foo is a struct type, it will not; if it's a class type, it will.

Contrary to what Mr. Lippert says, your type may be just fine as a struct, with a couple of caveats:

  1. Structs should expose their fields directly, rather than via properties, unless the properties are going to have some non-trivial logic in them.
  2. Passing by value structs which are larger than 16 bytes is a fair bit slower than passing smaller ones, since .net has special handling for smaller structs. Passing by ref is not affected by struct size, though.
  3. Mutable structs which hold mutable reference types often exhibit semantics which are a weird cross between mutable value semantics and mutable reference semantics. That is not a problem for structs which hold immutable reference types like `string`, however.
  4. Properties of struct type are often a pain to work with. Read-only properties of reference types are sometimes easier to work with, but replacing a struct type that would hold 20 bytes of data, with a class that likewise holds 20 bytes of data, can almost double storage requirements on 32-bit systems, or more than double them on 64-bit systems.

Mutable-value-type semantics are useful. Older C# compilers (years ago) had some problems with them, and some people want to discourage people from learning to understand them, but those aren't good reasons to refrain from using them where appropriate.

Upvotes: 0

Eric Lippert
Eric Lippert

Reputation: 660034

I take it the above is more 'efficient' than using a class?

Absolutely not. That is a terrible struct. Structs should be small; no more than, say, four times the size of a reference; your struct is the size of five references on an 32 bit machine. Structs should represent values; this does not appear to represent any value. Structs should be immutable; this is chock full of mutability.

At what point, if I continued to add string properties, would it be time to convert the struct to a class?

The point to convert this structure to a class was the moment you created it. It should never have been a struct in the first place. Your default assumption should be that classes are good enough; only go to a struct when you have evidence that doing so solves a problem that you actually have.

I had planned to pass this struct around a GDI - centric application. I had always assumed structs were more performant when dealing with mainly value types.

Structs are more efficient than classes in a very small number of cases: when they are small, immutable, represent values, and are composed of other values, like integers. In other cases they are less efficient: because structs are copied by value, large structs can be much slower to use than references. Because structs are copied by value, mutable structs lead to bugs because you mutate copies when you think you are mutating variables. Because structs are copied by value, they should have the semantics of values, not references. And because structs that contain only other structs can be skipped by the garbage collector entirely, structs are only more efficient for cleanup purposes when they contain no references.

In any event, the way you tell if something is more efficient is try it both ways and measure its performance against your performance goals. Use science. Set a goal and measure it. Using structs "because I assume they are more efficient" is making technical decisions on the basis of hearsay. Measure, and then you'll know what is more efficient.

Upvotes: 35

Muhammad Maqsoodur Rehman
Muhammad Maqsoodur Rehman

Reputation: 34257

Remember that what ever you declare in a struct is public by defualt. You have to use a class instead if you want your data to be hidden. Apart from this all typical features of OOP are not available in struct.

FYI: Class (computer programming)

Upvotes: -3

3Dave
3Dave

Reputation: 29041

If you need the enhanced capabilities that a class offers, such as inheritance, then switch. If not, a struct can be a bit "lighter," but unless you anticipate some performance issues, such as garbage collection inside of a tight loop with a LOT of iterations, the necessity to pass structs around with ref whenever you want a method to make modifications, etc can create unnecessary work. (Though, in that example, destroying a struct that has reference-type properties also causes GC).

The practical upshot being: whether to use a struct or a class is a matter of your use case, not the number of properties that you have.

For a good explanation of the differences between and relative strengths and weakness of classes and structs, see this MSDN article.

For Eric Lippert's excellent note on garbage collection, structs and classes, see his response to this question.

Upvotes: 5

Jeggs
Jeggs

Reputation: 250

I dont think it's a case of if you keep adding strings, it's a case of what do you want to do with the object. Structs are value types and classes are reference types, there are some performance gains of structs from what I understand (in terms of memory heap/stack allocation) but I think ultimiately it depends on what you are doing with the object.

I THINK I read once that structs are great for short-lived lots of them objects, but I could be wrong.

Upvotes: 1

Related Questions