The main difference between class and struct are as follows:
a) Classes are created on heap while structs are created on stack.
b) Classes are passed by reference (by default) while structs are passed by
value.
v) Structs does not support inheritance.
Having said these differences, I belive structs is nothing but a data
structure that is exchanged and manipulated by various application elements
but structs itself does not have have any behaviour. I know structs could
have method/ functions but theoritically speaking, structs should "NOT" have
any behavior rather it is a data structure that holds data and is manipulated
by various classes.
Sorry, IMHO this is dead wrong.
Here are what I would consider better guidelines for choosing between
struct and class.
Use struct when you want a value type; use class in all other cases.
(There is one caveat... I'll get to that in a moment.)
So... when do you need a value type? When you need something that
would act like an int or a double or a DateTime: when you manipulate
it, you create a new one; they are immutable (once you create one you
can't change it); an instance of one has no identity. Let me expand on
those one by one.
First, when you manipulate an integer... say you negate it... you
don't actually change the integer itself. When you change 5 into -5
you do not change every 5 in your program into a -5. Instead, you
manipulate the value 5, get -5 as the result, and assign that result
to some variable (or back into the same variable that held the 5).
Every operation on a typical value type creates a new value.
This goes hand in glove with the "rule" that values are immutable.
It's sort of an odd concept to change a value "in place": usually you
do some operation to get a new value and then replace the old value
with the new one. There are exceptions in the .NET Framework (they're
the "caveat"... coming up shortly) but usually value types are
immutable.
The identity thing is an interesting angle that I dreamed up a while
back. If the thing you're creating has a UID, or could have a UID,
then it's a lousy candidate for a value type. You can't talk about
"this value 5" versus "that value 5" 5 is 5, and each copy of the
value 5 has nothing to distinguish it from the others. This is
different from "Bob Smith, customer #1234". In particular, it makes
sense to change some attribute of this customer #1234 and have every
reference to that customer in your entire program see that change. You
can't do that with value types. If you have more than one copy of a
reference type... more than one copy of customer #1234, then it's
usually something you've done deliberately: you have the "updated
customer #1234" versus the "original customer #1234" or something like
that. One doesn't expect to see objects with identities copied will-ye-
nil-ye all over your program, whereas with value types this is normal.
This is why I consider Tariq's advice to be dead wrong. If you make,
say, a customer record a value type, even though it may contain no
methods only fields, this will result in major frustration. The
problem is that a customer is usually something that you want to be
able to change and, when you do, you want all of the references to
that customer all over your program to see that change. Or, if you
want some of them to change but not others, then it's usually
something quite deliberate over which you want full control. If you
make it a value type, you'll change the one copy you're storing, and
if you want any other copies to see the change, you'll have to assign
the changed copy explicitly. In effect, you can end up with hundreds
of copies of "customer #1234" without really trying, and keeping those
copies in synch will be a nightmare. Very, very ugly.
And now, the caveat. In a few extreme situations, the .NET Framework
has chosen to make unlikely value types. Point and Rectangle come to
mind, but there are more. They are, unfortunately, mutable, more for
convenience of notation than for any other reason. These are the few
cases in which the Framework designers chose to make something a value
type for efficiency reasons, not necessarily because value semantics
were the logical choice (although making them values does change their
semantics). The efficiency gained here is that making these small
objects values eliminates the cost of allocating zillions of them on
the heap and then having to garbage collect them. In effect, Points
and Rectangles are used in calculations, or the designers expected
them to be used in calculations, and they didn't want intermediate
results to be allocated on the heap and therefore incur GC overhead to
clean them up.
The semantics do change, though: a Point value type is conceptually
different from a Point reference type, but that's fodder for another
post.
As far as value types having methods, absolutely they can, and most
likely will. I'll close with a common example to illustrate what I
mean.
I created a value type called Measure: it consists of a quantity and a
unit of measure, and it's used to represent things like "12 inches" or
"15 kilograms". That sort of thing. My Measure value type has all
sorts of methods. In addition to the usual overloads for arithmetic
operators, there are methods like this:
decimal kiloQuantity = productWeight.GetValueAs(UnitOfMeasure.Kilos);
or
UnitOfMeasure native = productWeight.NativeUnitOfMeasure;
The reason it's a value type is _not_ that it's somehow "lightweight"
or that it doesn't have any methods. It's a value type because I want
it to act like a value.
If you're familiar with C++, then you can think of it like this. In C+
+, "struct" and "class" mean almost the same thing. Whether it's a
value (stored on the heap, copied on assignment, etc) is something you
decide every time you create an object or assign it. In C++ you decide
over and over again, at each turn, whether you want something to act
like a value or like a reference type. For example, if you say
MyType foo;
in C++, then any new instance of MyType is copied into "foo" and
stored on the stack. If you say instead
MyType *foo;
then any new instance of MyType is referenced by "foo" and could be
stored anywhere (but most often on the heap). If you were to pass a
MyType to a method, you decide whether you want to pass a value or a
reference by the method signature: a * means pass a reference, no *
means pass a value.
In C# you decide these things once and for good up front. If you
declare something a struct, then it is allocated in-place and passed
by value (unless you specify the "ref" keyword explicitly). If you
declare something a class, then it is allocated on the heap and
references to it are passed about. If you want a copy, you have to
explicitly .Clone() it.
Which one you choose _normally_ does not hinge on efficiency concerns,
but how you want the thing to _act_, and 99% of the time you want
things to act like reference types, in my experience.