tags:

views:

685

answers:

9

Just wondering why we need struct if class can do all struct can and more? put value types in class has no side effect, I think.

EDIT: cannot see any strong reasons to use struct

A struct is similar to a class, with the following key differences:

  • A struct is a value type, whereas a class is a reference type.
  • A struct does not support inheritance (other than implicitly deriving from object).
  • A struct can have all the members a class can, except the following:
  • A parameterless constructor
  • A finalizer
  • Virtual members

A struct is used instead of a class when value type semantics are desirable. Good examples of structs are numeric types, where it is more natural for assignment to copy a value rather than a reference. Because a struct is a value type, each instance does not require instantiation of an object on the heap. This can be important when creating many instances of a type.

+5  A: 

Custom value types aren't absolutely necessary - Java does without them, for example. However, they can still be useful.

For example, in Noda Time we're using them pretty extensively, as an efficient way of representing things like instants without the overhead of an object being involved.

I wouldn't say that "class can do all struct can and more" - they behave differently, and should be thought of differently.

Jon Skeet
+1  A: 

Structs are also often required for performance reasons. Arrays of structs take quite a bit less memory, and get much better cache coherency than an array of object references. This is very important if you're working with something like a rendering system, and need to generate 5 million vertices, for example.

For details, see Rico Mariani's Performance Quiz + Answers.

Reed Copsey
A: 

For the average application developer, using classes is the norm. On the surface, classes make structs seem unnecessary, but when you dig deeper into the nitty-gritty details they are actually quite different.

See here for some differences between structs and classes.

The most well-known difference is that classes are reference-types and structs are value-types. This is important because it allows a library developer to control how instances of a data-type can be used.

Rouan van Dalen
A: 

1, performance. In some cases using structures we'll get much better performance.
2, data immutability. By changing some property of a struct you'll get a new struct. This is very useful in some cases
3, better control of in memory representation. We can exactly define how the struct is located in memory and this allows us to serialize and deserialize some binary data fast and efficiently.

zihotki
+1  A: 

Structs are useful simply because they are passed by value, which can actually be useful in certain algorithms. This is actually something that classes CAN'T do.

struct ArrayPointer<T>
{
    public T[] Array;
    public int Offset;
}

You can pass this structure to a method and the method can alter the value of Offset for its own needs. Meanwhile, once you return from the method, it will behave as if Offset never changed.

Robert Davis
A: 

In general, use a class.

Only use a struct when you absolutely need value type semantics.

Randolpho
Struct types do not "only live on the stack". An array of ints isn't on the stack. A class field of type int is not on the stack. A static field of type int is not on the stack. A local variable of type int that is in an iterator block is not on the stack. A local variable of type int that is a closed-over outer variable of an anonymous method or lambda expression is not on the stack... struct types are usually *not* on the stack, so saying "they can only live on the stack" is completely misleading. The value of structs is that you can put *lots of them on the heap for cheap*.
Eric Lippert
I didn't say structs only live on the stack, I said you should only *create* one when you want it to only live on the stack. Everything you said is absolutely true, but if the struct will only live while encapsulated in some other datatype, it should be a class. Only create a struct when it *must* live on the stack.
Randolpho
But there is no type, struct or otherwise, that *must* live on the stack. If what you require is something that *must live on the stack* then the language you want to be using is C, not C#. The reason to create struct types is because you want to *model something which is logically a value, not a reference*. You're conflating "lives on the stack", which is an implementation detail, with "has value semantics". Value types have value semantics no matter where they live.
Eric Lippert
@Randolpho: Eric's point is that creating a struct *doesn't* force it to live on the stack, so even if your type "must" live on the stack, it may well still not. Your answer certainly heavily implies that all structs live on the stack.
Jon Skeet
I also note that you're making the common error of "on the stack equals fast". Value types are copied by value, which means that even small ones can be more expensive to use than reference types when copied frequently; the burden of the slow, frequent copies outweighs the tiny difference in allocation and deallocation efficiency. The performance benefit of value types is not that they are *fast* but that they are *small* and *compactable*. A million boxed ints takes up way more space than a million unboxed ints.
Eric Lippert
I see your point about small and compactable. For the record, I realize that not all value types live on the stack and that stack != fast, but I realize my post is misleading. I will edit appropriately.
Randolpho
Needing a value type semantic is a (almost) necessary, but not sufficient criterion to use structs.
Lawnmower
@Lawnmower: what *would* be a sufficient criterion to use structs that has nothing to do with value type semantics?
Randolpho
@Randolpho that's a difficult question. Probably there is none, or at least not a single one. What I tried to say is that there are lots of situations where you "absolutely need value type semantics" but structs are the wrong choice. Reading your answer again, it doesn't imply otherwise.
Lawnmower
@Lawnmower: I guess I'm confused by the downvote, then. I answered the question to say that a struct should be avoided unless value type semantics are absolutely necessary. This answer is compatible with your own opinion that structs are the wrong choice.
Randolpho
A: 

It is almost a must to use for interop with underlying data structure used by win32 API. I suppose a very big reason to have it in .net could be due to that reason.

Fadrian Sudaman
+5  A: 

Why use a struct when a class works? Because sometimes a class doesn't work.

In addition to the performance reasons mentioned by Reed Copsey (short version: fewer objects that the GC needs to track, allowing the GC to do a better job), there is one place where structures must be used: P/Invoke to functions that require by-value structures or structure members.

For example, suppose you wanted to invoke the CreateProcess() function. Further suppose that you wanted to use a STARTUPINFOEX structure for the lpStartupInfo parameter to CreateProcess().

Well, what's STARTUPINFOEX? This:

typedef struct _STARTUPINFOEX {
    STARTUPINFO                    StartupInfo;
    PPROC_THREAD_ATTRIBUTE_LIST    lpAttributeList;
} STARTUPINFOEX, *LPSTARTUPINFOEX;

Notice that STARTUPINFOEX contains STARTUPINFO as its first member. STARTUPINFO is a structure.

Since classes are reference types, if we declared the corresponding C# type thus:

[StructLayout(LayoutKind.Sequential)]
class STARTUPINFO { /* ... */ }

class STARTUPINFOEX { public STARTUPINFO StartupInfo; /* ... */ }

The corresponding in-memory layout would be wrong, as STARTUPINFOEX.StartupInfo would be a pointer (4 bytes on ILP32 platforms), NOT a structure (as is required, 68 bytes in size on ILP32 platforms).

So, to support invoking arbitrary functions which accept arbitrary structures (which is what P/Invoke is all about), one of two things are necessary:

  1. Fully support value types. This allows C# to declare a value type for STARTUPINFO which will have the correct in-memory layout for marshaling (i.e. struct support, as C# has).

  2. Some alternate syntax within P/Invokeable structures which would inform the runtime marshaler that this member should be laid out as a value type instead of as a pointer.

(2) is a workable solution (and may have been used in J/Direct in Visual J++; I don't remember), but given that proper value types are more flexible, enable a number of performance optimizations not otherwise achievable, and make sensible use within P/Invoke scenarios, it's no surprise that C# supports value types.

jonp