Structs vs. Classes

D

Dom

I'm really confused by the difference between a Struct and a Class?
Sometimes, I want just a group of fields to go together. A Class
without methods seems wrong, in that it carries too much overhead (I
think). A Struct seems more appropriate. At least it is what I would
have used in other languages. But since a Struct *can* hold methods,
I wander if I am saving anything. If not, why use it?
 
D

Diego Jancic

Hi,
The main difference is that Classes are by reference, but the structs
are passed by value, like the String type.
So Classes are faster than Structures..

Bye,
Diego
 
D

Dom

Well, fine. But I have to ask, what is the proper use of a Struct?
Would I ever use it instead of a Class?
 
A

Alun Harford

Diego said:
Hi,
The main difference is that Classes are by reference, but the structs
are passed by value, like the String type.
So Classes are faster than Structures..

Eugh.
It depends on what you're doing. Think about why ints are passed by
value, as an extreme example.

Alun Harford
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Dom said:
I'm really confused by the difference between a Struct and a Class?
Sometimes, I want just a group of fields to go together. A Class
without methods seems wrong, in that it carries too much overhead (I
think). A Struct seems more appropriate. At least it is what I would
have used in other languages. But since a Struct *can* hold methods,
I wander if I am saving anything. If not, why use it?

Structs is value types. Classes is reference types.

There are some different performance characteristics of
those, but it is a rather complex story.

If you go by the rule of using struct for bundling
data with no methods locally withing methods or at
least within assemblies and then use class for all
other, then you will be OK in 99% of cases.

And when you learn more about value types and
reference types, then you will really know.

Arne
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Diego said:
The main difference is that Classes are by reference, but the structs
are passed by value, like the String type.

Both classes and structs are default passed by value and both
can be passed by reference. Passing a reference type bu value
and passing a value type by reference is not the same.
So Classes are faster than Structures..

Sometimes. Definitely not always.

Arne
 
D

Dom

Both classes and structs are default passed by value

Are you sure about this? From MS help: "When passing a struct to a
method, it is passed by value instead of as a reference."

I think the implication is that classes are passed by reference.
 
D

Dom


Then I'm confused by this from MS help: "This example shows that when
a struct is passed to a method, a copy of the struct is passed, but
when a class instance is passed, a reference is passed."

Maybe it's a question of semantics. Your saying that the variable
itself is passed by value. The example shows that this variable can
not be made to point to a new object, except locally. But the
important point is that (I think) when you pass a struct, the entire
struct is placed on the call stack. If the struct is 5 long words,
then all 5 long words are there. When you pass an object, the single
reference is placed on the call stack, not all the fields. Your point
is just that a copy of the reference is placed there.
 
?

=?ISO-8859-1?Q?Arne_Vajh=F8j?=

Dom said:
Then I'm confused by this from MS help: "This example shows that when
a struct is passed to a method, a copy of the struct is passed, but
when a class instance is passed, a reference is passed."

Maybe it's a question of semantics. Your saying that the variable
itself is passed by value. The example shows that this variable can
not be made to point to a new object, except locally. But the
important point is that (I think) when you pass a struct, the entire
struct is placed on the call stack. If the struct is 5 long words,
then all 5 long words are there. When you pass an object, the single
reference is placed on the call stack, not all the fields. Your point
is just that a copy of the reference is placed there.

Exactly.

Arne
 
G

Guest

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.

--
Tariq Karim | Capgemini | El-Segundo
Senior Consultant | Telecom Media and Entertainment
Mobile: +01 832-433-6055 | www.capgemini.com
Join the Collaborative Business Experience
 
B

Bob Grommes

Dom,

In my experience, in .NET, most of the time when I start out with a
struct I end up changing it to a class because it ends up needing to use
inheritance or in some other way evolves into something that's more
appropriately represented as a class. IIRC there can also be versioning
issues if you expose a struct publicly and then need to change it to a
class later.

In most real-world line of business app development, there is so little
overhead savings with structs that it's probably fine to default to
classes unless you stumble onto a compelling need for a struct. I
seldom see them in other people's code, either.

If you are implementing something that will be using value semantics,
that's one thing, but most of what is useful in that regard is built
into the CLR already. I don't see structs as something that's commonly
going to be used in everyday line of business development. Unless
you're doing something really demanding like manipulating huge matrices
or some kinds of game development for instance, the question of structs
vs classes is not something you need to expend bandwidth on.

--Bob
 
P

Peter Duniho

Are you sure about this? From MS help: "When passing a struct to a
method, it is passed by value instead of as a reference."

I think the implication is that classes are passed by reference.

There's "reference", and then there's "reference". Clear? :)

What Arne is saying is that the parameter passing method of both classes
and structs is "by value". *BUT* (and this is a pretty big "but"),
because the "value" of a class is always a reference, they are in another
sense of the word always passed by reference.

In C++, you can instantiate a class on the stack, or as a global, but in
C# all classes are always allocated from the heap and they are always
referred to by a reference to the instance. So in that sense, you are
correct that they are passed via that reference.

But in terms of the definition of "passing by reference", they are not
passed by reference. The reference to the class is passed, yes...but that
reference is passed "by value". If it were passed "by reference", then
the variable holding the reference itself could be changed (and that is
the case when the "ref" or "out" keyword is used).

Structs, on the other hand, being "value" types always need a place to
keep them, and aren't referred to by reference. So when you pass a struct
"by value", the whole struct is passed.

IMHO, this all is one of the more confusion areas of C#, especially
because you still need to use the "new" keyword to initialize a struct.
It makes it look like you are creating a new instance, just as happens
with a class, and assigning the reference to that instance to (for
example) a local variable. But that's not what happens. The storage for
your struct is represented by that local variable itself, not a reference
to a newly allocated place in memory.

I'm fine with the behaviors of structs and classes being different (even
though in C++ they are practically the same), but IMHO it was a mistake to
keep the syntax of the two the same as well. It only leads to confusion.

Pete
 
J

Jon Skeet [C# MVP]

Dom said:
Then I'm confused by this from MS help: "This example shows that when
a struct is passed to a method, a copy of the struct is passed, but
when a class instance is passed, a reference is passed."

Yes - a reference is passed. That's not the same as "passing the object
by reference."
Maybe it's a question of semantics. Your saying that the variable
itself is passed by value. The example shows that this variable can
not be made to point to a new object, except locally. But the
important point is that (I think) when you pass a struct, the entire
struct is placed on the call stack. If the struct is 5 long words,
then all 5 long words are there. When you pass an object, the single
reference is placed on the call stack, not all the fields. Your point
is just that a copy of the reference is placed there.

Exactly - because the value of the variable (or other reference type
expression) isn't the object itself, it's just a reference.

In both the struct and the class case, the value of the expression is
passed by value: the expression is evaluated, and the value of the
expression is copied as the initial value of the parameter within the
called method.

Passing by reference is subtly different - see the page I referenced in
my other post for more details.
 
J

Jon Skeet [C# MVP]

I'm fine with the behaviors of structs and classes being different (even
though in C++ they are practically the same), but IMHO it was a mistake to
keep the syntax of the two the same as well. It only leads to confusion.

I think it's a problem which will diminish over time, leaving the
benefit of consistency of how you create new instances of a type,
whether they're reference or value types.

I believe most of the confusion is for migrating C++ programmers, who
are used to "new" *always* creating a new object on the heap.
 
J

Jon Skeet [C# MVP]

Tariq Karim said:
The main difference between class and struct are as follows:

a) Classes are created on heap while structs are created on stack.

Class instances are indeed always created on the heap, at least with
C#, with the exception of fixed arrays which can be created on the
stack in unsafe code.

However, value type instances are *often* on the heap - as part of
other instances. If I do:

class Foo
{
int i;
}

Foo f = new Foo();

The object referred to by f is on the heap, including its "i" member.
See http://pobox.com/~skeet/csharp/memory.html for more on this.
b) Classes are passed by reference (by default) while structs are passed by
value.

No. See http://pobox.com/~skeet/csharp/parameters.html
v) Structs does not support inheritance.

They support interface inheritance, but not implementation 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.
No...

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.

Just because they don't have behaviour in *some* languages doesn't mean
they shouldn't have behaviour in C# or .NET. Why should something being
a value type mean that it shouldn't have behaviour? Would you rather
DateTime didn't have any methods in it? That you couldn't use
int.ToString()?
 
J

Jon Skeet [C# MVP]

Dom said:
I'm really confused by the difference between a Struct and a Class?
Sometimes, I want just a group of fields to go together. A Class
without methods seems wrong, in that it carries too much overhead (I
think). A Struct seems more appropriate. At least it is what I would
have used in other languages. But since a Struct *can* hold methods,
I wander if I am saving anything. If not, why use it?

See http://pobox.com/~skeet/csharp/references.html
It's still a work in progress, but hopefully it'll give you the gist of
it.

Don't be concerned about the overhead of making something a class -
just consider whether you really want a value type or a reference type.
As a rule of thumb, it's pretty rare to create a new value type in your
own code, although of course you'll be *using* value types (like int)
all the time.
 
B

Bruce Wood

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.
 
P

Peter Duniho

I think it's a problem which will diminish over time, leaving the
benefit of consistency of how you create new instances of a type,
whether they're reference or value types.

I believe most of the confusion is for migrating C++ programmers, who
are used to "new" *always* creating a new object on the heap.

Possibly. And yet a) most C# programmers, at least for the near future,
will in fact be C++ programmers migrating, and b) even if we reach a point
where most C# programmers are indeed ones who started out with C# and thus
have been indoctrinated in the languages subtle quirks, that does not in
my mind change the fact that having a "new" operator do two very different
things depending on the type of object on which it's operating is just not
a great idea.

Note that, at least in my view, there *isn't* consistency of how you
create new instances of a type. When you use the "new" operator with a
struct, you aren't really creating a new instance of that type. The new
instance of a struct is created when the containing object is created
(whether that's on the stack, or in a class, or another struct). The
"new" operator doesn't really create the instance that you're using.

So I'm not really on board with respect to your thought that over time,
we'll be left with "the benefit of consistency of how you create new
instances of a type". I don't see that consistency today, and so don't
see that we'll be left with that in the future.

It's a classic example of inappropriate operator overloading, IMHO. It
falls in with other C#/.NET "features", such as the use of the word
"event" to describe something very different from a "WaitableEvent", as
well as the use of the method name "Invoke()" to describe one thing in the
Form class, and something somewhat different on a delegate.

It's certainly not a big deal...any person spending any significant amount
of time with C# can easily get accustomed to these issues. But they do
detract from the general theme of C# and .NET of trying to avoid apparent
ambiguity.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top