tags:

views:

3844

answers:

12

MSDN says that you should use structs when you need lightweight objects. Are there any other scenarios when a struct is preferable over a class?

Edit:
Some people have forgotten that:
1. structs can have methods!
2. structs have no inheritance capabilites.

Another Edit:
I understand the technical differences, I just don't have a good feel for WHEN to use a struct.

+6  A: 

Use a struct when you want value-type semantics instead of reference-type. Structs are copy-by-value so be careful!

Also see previous questions, e.g.

http://stackoverflow.com/questions/13049/whats-the-difference-between-struct-and-class-in-net

Simon Steele
A: 

when you don't really need behavior, but you need more structure than a simple array or dictionary.

Follow up This is how I think of structs in general. I know they can have methods, but I like keeping that overall mental distinction.

James Deville
Why do you say that? Structs can have methods.
Esteban Araya
A: 

As @Simon said, structs provide "value-type" semantics so if you need similar behavior to a built-in data type, use a struct. Since structs are passed by copy you want to make sure they are small in size, about 16 bytes.

Scott Dorman
Ouch, 16K? That's rather large to be making a copy every method call!
OwenP
@OwenP, you're right...should have been 16 bytes. Corrected.
Scott Dorman
A: 

I use it when I have to encapsulate only data without any methods.

How come? Structs can have methods as well.
Esteban Araya
@Esteban: you're right, but the author of the post is not saying they can't.
petr k.
A: 

Just a reminder - what most people tend to forget in this context is that in C# structs can have methods as well.

petr k.
A: 

I think this is a duplicate of this question!

http://stackoverflow.com/questions/37931/whats-the-use-of-value-types-in-net

Luke Halliwell
No, I'm not asking quite the same thing. Thanks for the pointer, however.
Esteban Araya
+1  A: 

I would use structs when:

  1. an object is supposed to be read only(every time you pass/assign a struct it gets copied). Read only objects are great when it comes to multithreaded processing as they don't requite locking in most cases.

  2. an object is small and short-living. In such a case there is a good chance that the object will be allocated on the stack which is much more efficient than putting it on the managed heap. What is more the memory allocated by the object will be freed as soon as it goes outside its scope. In other words it's less work for Garbage Collector and the memory is used more efficient.

Pawel Pabich
+67  A: 

MSDN has the answer: Choosing Between Classes and Structures.

Basically, that page gives you a 4-item checklist and says to use a class unless your type meets all of the criteria.

Do not define a structure unless the type has all of the following characteristics:

  • It logically represents a single value, similar to primitive types (integer, double, and so on).
  • It has an instance size smaller than 16 bytes.
  • It is immutable.
  • It will not have to be boxed frequently.
OwenP
Thanks Owen. That's exactly what I was looking for.
Esteban Araya
Nice succinct reference (+1).
Keith
Thanks the link is very usefull
CheGueVerra
Maybe I'm missing something obvious but I don't quite get the reasoning behind the "immutable" part. Why is this necessary? Could someone explain it?
DrJokepu
I guess it's another way to say "it has value semantics"
Trap
They've probably recommended this because if the struct is immutable, then it won't matter that it has value semantics rather than reference semantics. The distinction only matters if you mutate the object/struct after making a copy.
Stephen C. Steel
A: 

Another time one might choose struct instead of class is for template metaprogramming as shorthand for class with public access. This cuts down on verbosity. Also with template metaprogramming, the run-time criteria one might use to choose between class and struct often don't apply because no actual runtime objects are likely to ever exist if the struct (or class) is used only to manipulate the compile-time type system. For example:

struct five {
    static int const value = 5;
    typedef int value_type;
};

[code sample from C++ Template Metaprogramming by David Abrahams and Aleksey Gurtovoy, page 18]

jwfearn
This is for .net.
TraumaPony
+2  A: 

I have always used a struct when I wanted to group together a few values for passing things back from a method call, but I won't need to use it for anything after I have read those values. Just as a way to keep things clean. I tend to view things in a struct as "throwaway" and things in a class as more useful and "functional"

Ryan Skarin
A: 

Hmm...

I wouldn't use garbage collection as an argument for/against the use of structs vs classes. The managed heap works much like a stack - creating an object just puts it at the top of the heap, which is almost as fast as allocating on the stack. Additionally, if an object is short-lived and does not survive a GC cycle, deallocation is free as the GC only works with memory that's still accessible. (Search MSDN, there's a series of articles on .NET memory management, I'm just too lazy to go dig for them).

Most of the time I use a struct, I wind up kicking myself for doing so, because I later discover that having reference semantics would have made things a bit simpler.

Anyway, those four points in the MSDN article posted above seems a good guideline.

+4  A: 

I am surprised I have not read at any of the previous answer this, which I consider the most crucial aspect :

I use structs when I want a type with no identity. For example a 3D point:

public struct ThreeDimensionalPoint
{
    public readonly int X, Y, Z;
    public ThreeDimensionalPoint(int x, int y, int z)
    {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }

    public override string ToString()
    {
        return "(X=" + this.X + ", Y=" + this.Y + ", Z=" + this.Z + ")";
    }

    public override int GetHashCode()
    {
        return (this.X + 2) ^ (this.Y + 2) ^ (this.Z + 2);
    }

    public override bool Equals(object obj)
    {
        if (!(obj is ThreeDimensionalPoint))
            throw new ArgumentException();
        ThreeDimensionalPoint other = (ThreeDimensionalPoint)obj;
        return this == other;
    }

    public static bool operator ==(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
    {
        return p1.X == p2.X && p1.Y == p2.Y && p1.Z == p2.Z;
    }

    public static bool operator !=(ThreeDimensionalPoint p1, ThreeDimensionalPoint p2)
    {
        return !(p1 == p2);
    }
}

If you have two instances of this struct you don't care if they are a single piece of data in memory or two. You just care about the value(s) they hold.

Andrei Rinea