468,773 Members | 2,338 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,773 developers. It's quick & easy.

When, why and where should a struct be used?

Documentation [1] tells me how but not when, why or where...

<%= Clinton Gallagher

[1] http://msdn2.microsoft.com/en-us/lib...w4(VS.80).aspx
Apr 13 '06 #1
46 2212
Hello clintonG,

Topic was raised 2 days ago http://groups.google.ru/group/micros...7802400b8127a8

c> Documentation [1] tells me how but not when, why or where...
c>
c> <%= Clinton Gallagher
c>
c> [1] http://msdn2.microsoft.com/en-us/lib...w4(VS.80).aspx
c>
---
WBR,
Michael Nemtsev :: blog: http://spaces.msn.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsche
Apr 13 '06 #3
I will try to give a simle answer gloassing over as many technical
issues as I can...

Structs are an "old school" method of combineing data elements into one
unit.

Class came along afterwards, they are esentuly a struct which allows
for things like inheritance and other OO stuff.

Structs being somewhat simpler creatures are "lean and mean", that is
they work fast but lack features.

Example .NET stucts Point, Rectangle DateTime. Note how these are
simple operations which are often performance critical.

Classes are usefull when things get more complicated. Ie you need
inheritance or something.

Struct and Classes have different pitfals that may suprise the new
programmer.
ie

a struct can not be nul but a class can..
struct a = stuct b copyies bto a
class a = class b means a is also called b.

hope this "basic" overview helps.

-dm

Apr 13 '06 #4
<th*********@gmail.com> wrote:

<snip>
Structs being somewhat simpler creatures are "lean and mean", that is
they work fast but lack features.


This is a vast oversimplification. Structs are very often *not* the
faster (or leaner) solution. For instance, if you have a struct with
100 fields in, that will be much larger and slower to pass as a
parameter into a method than a single reference would be.

One day I'll get round to writing up a full article on types and
particularly the difference between value types and reference types.
They are fundamentally different - it's not that one is a "leaner and
meaner" version of the other.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Apr 13 '06 #5


Jon Skeet [C# MVP] wrote:
<th*********@gmail.com> wrote:

<snip>
Structs being somewhat simpler creatures are "lean and mean", that is
they work fast but lack features.

This is a vast oversimplification. Structs are very often *not* the
faster (or leaner) solution. For instance, if you have a struct with
100 fields in, that will be much larger and slower to pass as a
parameter into a method than a single reference would be.

One day I'll get round to writing up a full article on types and
particularly the difference between value types and reference types.
They are fundamentally different - it's not that one is a "leaner and
meaner" version of the other.


Why are structs passed as value parameters ? What's the difference (logically)

eg Given a function
void fn ( typea p1, typeb p2 )
{
}

which is the value parameter if one of the types is a class and one a struct ?

Why differentiate between classes and simple types rather than say having all
parameters passed by reference and having a val keyword ( or vice versa) ?

I'm sure there's a good reason, but I don't know C# well enough.

In C++, I typically use structs to describe say the structure of a byte stream eg

#pragma pack ( push, 1 )
typedef struct Hdr
{
unsigned char soh;
unsigned char fld [ 2 ];
}
Hdr;

etc
Apr 13 '06 #6

"Ian Semmel" <is***********@NOKUNKrocketcomp.com.au> wrote in message
news:uI**************@TK2MSFTNGP03.phx.gbl...


Jon Skeet [C# MVP] wrote:
<th*********@gmail.com> wrote:

<snip>
Structs being somewhat simpler creatures are "lean and mean", that is
they work fast but lack features.

This is a vast oversimplification. Structs are very often *not* the
faster (or leaner) solution. For instance, if you have a struct with 100
fields in, that will be much larger and slower to pass as a parameter
into a method than a single reference would be.

One day I'll get round to writing up a full article on types and
particularly the difference between value types and reference types. They
are fundamentally different - it's not that one is a "leaner and meaner"
version of the other.


Why are structs passed as value parameters ? What's the difference
(logically)


Because that is (partly) what structs are for in C#
eg Given a function
void fn ( typea p1, typeb p2 )
{
}

which is the value parameter if one of the types is a class and one a
struct ?
the struct is.

Why differentiate between classes and simple types rather than say having
all parameters passed by reference and having a val keyword ( or vice
versa) ?
This is to do with the fact that value types (structs) can be on the stack
or inside objects on the heap whereas reference types (classes) cannot.
These limitations ensure that there are references into the stack or into
the guts of an object on the heap. If there were then GC would be extremely
difficult if not impossible consequently you cannot pass structs by
reference.

I suppose that in principle you could pass reference types by value but what
would be the point.

I'm sure there's a good reason, but I don't know C# well enough.

In C++, I typically use structs to describe say the structure of a byte
stream eg


There is no way to know or influence the memory layout of anything in C#
(although there are ways to influence how something is marshalled when
calling C/C++ this is NOT the same as saying how it is stored in memory).

struct and class are virtually synonymous in C++ whereas they are quite
different in C#
Apr 13 '06 #7
Ian Semmel wrote:
One day I'll get round to writing up a full article on types and
particularly the difference between value types and reference types.
They are fundamentally different - it's not that one is a "leaner and
meaner" version of the other.
Why are structs passed as value parameters ? What's the difference (logically)

eg Given a function
void fn ( typea p1, typeb p2 )
{
}

which is the value parameter if one of the types is a class and one a struct ?


Both are. Both parameters are passed by value. One of the parameters is
itself a reference, the other isn't.
Why differentiate between classes and simple types rather than say having all
parameters passed by reference and having a val keyword ( or vice versa) ?
That's exactly what we've got - pass by value is the default, and you
can specify to pass by reference. However, you need to be aware that
what you're passing in the case of a reference type is a reference.
That's not the same as pass-by-reference semantics, although it's
similar in many respects.

See http://www.pobox.com/~skeet/csharp/parameters.html for more details
on this.

When you do something like:

ArrayList a = new ArrayList();
the value of a is a reference to an ArrayList - it isn't the ArrayList
object itself.

Now, when you do:
int x = 5;
the value of x *is* the integer.
I'm sure there's a good reason, but I don't know C# well enough.

In C++, I typically use structs to describe say the structure of a byte stream eg


<snip>

C++ is somewhat different, I believe. I don't know C++ well enough to
talk confidently about it, but I *believe* that a struct in C# is
roughly equivalent to a class in C++. When you declare a variable
(parameter, whatever) in C#, that's like declaring the variable as a
pointer in C++:

C#: SomeType a;
C++: SomeType *a;

As I say, some of the C++ terminology *may* be a little off here - I
apologise if so.

Jon

Apr 13 '06 #8
Nick Hounsome wrote:
Why are structs passed as value parameters ? What's the difference
(logically)
Because that is (partly) what structs are for in C#
eg Given a function
void fn ( typea p1, typeb p2 )
{
}

which is the value parameter if one of the types is a class and one a
struct ?


the struct is.


No - both are value parameters. In both cases, the value of the
expression used as the argument is evaluated, and that value becomes
the initial value of the parameter.
From the C# spec:


<quote>
A parameter declared without a ref or out modifier is a value
parameter.
</quote>

Here, neither parameter is declared with a ref or out modifier, so both
are value parameters.

Jon

Apr 13 '06 #9
Sorry, but you're wrong on most counts. You're thinking of "struct" as
it exists in C++ or C, not C#. C# structs are very different. Read the
links to the threads given in the other posts.

the.duck...@gmail.com wrote:
I will try to give a simle answer glossing over as many technical
issues as I can...

Structs are an "old school" method of combineing data elements into one
unit.
In C++ this is true. It is not true in C#. In fact, using them this way
in C# is a sure road to frustration and bad code.
Class came along afterwards, they are esentuly a struct which allows
for things like inheritance and other OO stuff.
Historically, in C++, this is true, but not for C#. Everything changed
in C#.
Structs being somewhat simpler creatures are "lean and mean", that is
they work fast but lack features.
A vast oversimplification that overlooks the primary difference between
struct and class in C#: classes are reference types and structs are
value types. This has implications for how they are assigned, passed to
methods, and returned as results from methods and properties. It also
has implications for garbage collection. All of this means that structs
_may_ give you a performance increase, or _may_ cause performance
degradation, depending upon how you use them.

Unless you understand the difference between value semantics and
reference semantics and why and when one would want one rather than the
other, you will not know where it's appropriate to use a value type
(struct) to gain efficiencies.

Anyway, most value types you'll create will be because you want value
semantics, not for the sake of speed. There are only a few cases I can
think of where something was made a value type for efficiency's sake;
those are Point and Rectangle, and even then the Framework designers
had to make a decision to subtly change their semantics: a Point struct
has different semantic implications from a Point class.
Example .NET stucts Point, Rectangle DateTime. Note how these are
simple operations which are often performance critical.
Well, yes, but you don't say why. The reason is garbage collection: if
you're doing thousands or millions of coordinate calculations, then you
don't want to be stuck garbage collecting thousands or millions of
little Points off the heap. Making it a struct means that it doesn't
need to be GC'd. However, making it a struct changes its semantics
subtly: a Point now becomes a _value_, and as such there's no more
concept of "this point 4,6" as opposed to "that point 4,6". The
coordinates 4,6 become a value that is copied everywhere, just like
"the integer 5". A Point class would give you the possibility of
(cleanly) having several copies of 4,6 that were distinct and could be
manipulated.
Classes are usefull when things get more complicated. Ie you need
inheritance or something.
No... classes are useful when you want reference semantics, which is
almost always, and certainly whenever you have objects that have
_identity_: a customer, a sales order, the sales figures for a
particular year, stuff like that.
struct a = stuct b copyies bto a
class a = class b means a is also called b.


True, but these are hardly "pitfalls": this behaviour is the very
reason why you would choose one over the other.

As I said, please read the other threads that were linked earlier in
this thread. Those discussions clearly outline the pros and cons of
structs versus classes.

Apr 13 '06 #10
In C#, structs are value types, and classes are reference types.

Bottom line: use a struct when you *want* value-type semantics, and use
a class for every other case.

Check out the following for information on the difference between a
value and a reference in C#:

http://www.albahari.com/value%20vs%2...e%20types.html

Apr 13 '06 #11
ra*******@gmail.com wrote:
Check out the following for information on the difference between a
value and a reference in C#:

http://www.albahari.com/value%20vs%2...e%20types.html


Not a bad article on the low-level handling of classes versus structs
where memory allocation is concerned, although it contains a few minor
bloopers:
When a method is invoked, the CLR bookmarks the top of the stack, and then
allocates memory on top of this for any value type objects (including local variables)
that are created.
In fact, the only value types for which the CLR leaves space in a stack
frame are method arguments, local variables, and method results. The
article mentions only later that value types that are fields in classes
are created on the heap along with all of the other information for the
class instance.
All classes descending from MarshalByRefComponent (including all Windows Forms
controls) have a Dispose method. This method must be called when an object is no
longer needed in order to release resources other than memory.
Well, yes, but there's another way that the Dispose method is called,
and that's by the garbage collector just before it reclaims an object.
So, it's not _entirely_ necessary that Dispose be called on an object
before it goes out of scope... it's just better practice because it
releases unmanaged resources sooner. (At least, that's my
understanding... someone please correct me if I'm wrong.)
You might wonder if they could they have saved all this bother by defining Size as a
class rather than a struct. But this would have two negative implications....


The author mentions two relatively unimportant consequences of making
Size a class and forgets to mention the most important one: if you are
creating many, many Sizes, Points, or Rectangles (which the WinForms
classes do on a regular basis) and they were classes, then every one of
those little things would have to be cleaned up by the garbage
collector at some point. Making them value types means that they never
need to be GC'd (unless they're boxed).

As I said, not a bad article, but it doesn't really tell you why you'd
want to make something a class rather than a struct or vice versa.

Apr 13 '06 #12
<snip />
As I said, not a bad article, but it doesn't really tell you why you'd


And that's what I'm still trying to figure out -- beyond the value/reference
context -- but this topic sure stirs it up yea heh?

<%= Clinton Gallagher
Apr 13 '06 #13
Thanks for all the replies, very insightful.

<%= Clinton Gallagher

"clintonG" <cs*********@REMOVETHISTEXTmetromilwaukee.com> wrote in message
news:uH**************@TK2MSFTNGP04.phx.gbl...
Documentation [1] tells me how but not when, why or where...

<%= Clinton Gallagher

[1] http://msdn2.microsoft.com/en-us/lib...w4(VS.80).aspx

Apr 13 '06 #14
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:11**********************@v46g2000cwv.googlegr oups.com...
<snip>
C++ is somewhat different, I believe. I don't know C++ well enough to
talk confidently about it, but I *believe* that a struct in C# is
roughly equivalent to a class in C++.


Hi Jon,

It has been a while, however, if I remember correctly.

In C++ there is NO difference between a class and a struct EXCPEPT
The default access qualifier for members is public for structs
The default access qualifier for members is private for classes

Bill
Apr 14 '06 #15


Jon Skeet [C# MVP] wrote:
Nick Hounsome wrote:
Why are structs passed as value parameters ? What's the difference
(logically)


Because that is (partly) what structs are for in C#

eg Given a function
void fn ( typea p1, typeb p2 )
{
}

which is the value parameter if one of the types is a class and one a
struct ?


the struct is.

No - both are value parameters. In both cases, the value of the
expression used as the argument is evaluated, and that value becomes
the initial value of the parameter.
From the C# spec:


<quote>
A parameter declared without a ref or out modifier is a value
parameter.
</quote>

Here, neither parameter is declared with a ref or out modifier, so both
are value parameters.

Jon


Actually, I've worked it out (to my way of thinking )

C#
void fn ( cl p )
C++
void fn ( cl* p)

C#
void fn ( ref cl p )
C++
void fn ( cl*& p )

C#
void fn ( struc_thing s )
C++
void fn ( struc_thing s )
Apr 14 '06 #16
Well, as I said in the other thread. 99.9% of the time you want a
class.

You want a struct when you want the thing to act like a primitive
type-for example, if you want to do mathematics with it-and you
don't terribly mind that it won't have any sort of identity: it will be
copied all over the place and one copy is semantically the same as any
other.

What I mean by that last bit is that, for example "customer" would make
for a lousy struct: usually you think of having one instance for each
customer, with everyone pointing at the same instance (for a single
customer). You create copies for specific reasons, like making a new
version to write back the database (as opposed to the original one you
read in, which you might be holding somewhere). You don't really think
of a customer as a "value" that is copied whenever it's assigned. Most
types you create will be like this.

However, a few things, like a Fraction (one of my value types), you
_do_ want it to act like a primitive type (the same way that decimal
acts, for example): you want to do math with it, and every time you
assign it or do some operation on it you want the result to be a copy:
you don't want to alter the number 1.5 so that every variable holding
1.5 now contains 1.7. That makes no sense. Similarly, you don't want to
modify 3 3/4 so that every variable holding it now holds 5 1/2. You
want to do some operation that results in a new value, 5 1/2, and then
store it in some variable, just the way that a decimal type works.

Take a look at the standard type System.Drawing.Point, and notice the
subtle difference between making it a class and making it a struct.

One fellow posted here that he wanted to create a drawing program that
allowed his users to place points on the screen and join them into
polygons. Then allow the user to manipulate the vertices of the polygon
on the screen. He was wondering how to do that with the standard Point
value type. The answer is that he would be better off creating a new
_class_ called Vertex, which might use Point to store its coordinates,
but which is a _class_. Why? Because if the user were to place two
vertices of two polygons at the location (4, 6), you want them to
remain distinct vertices. Since a value type has no "identity" (one
copy of (4, 6) is equivalent to any other copy of (4, 6)), this doesn't
work too well with value types. You need a class, because Vertex
objects as reference types would have _identity_: _this_ (4, 6) is
distinct from _that_ (4, 6).

By making Point a struct, MS gained some GC efficiency, but also gave
it specific semantics: Points are commodities. The only thing that
distinguishes one from another are its coordinates, its value, and if
two have the same coordinates then you can't tell whether they're
distinct points or just copies of one another. This the same as when
you have two variables containing the value 5: any distinction between
them exists only in code. There is no way that you can "mark" this
value 5 to distinguish it from that value 5. It's just 5. Classes are
different: two instances are distinct even if they contain the same
data, because they have different references (different addresses).

Anyway, you almost never want value semantics in a type you create. You
almost always want your types to have reference semantics: each
instance you create is distinct from all other instances (even if it
contains the same state, the same values in its members), and if you
want to create a copy of one you do so explicitly (via Clone).

It's only in those few cases in which you want a new type that acts
like a primitive, like int or double or DateTime, that you would use
struct.

Finally, if you do create a struct, and you think that you need it to
be mutable (you need property setters, or methods that change a value
rather than returning a new value) then you are probably abusing the
construct. This rule is not 100%: notice that Microsoft made Point
mutable, for example (you can say myPoint.X = 6), a decision with which
I don't entirely agree, by the way. The linked article showed the kinds
of (apparently) odd behaviour that can result, so I prefer immutable
structs on those rare occasions when I create one.

Apr 14 '06 #17
Bill Butler <qw****@asdf.com> wrote:
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:11**********************@v46g2000cwv.googlegr oups.com...
<snip>
C++ is somewhat different, I believe. I don't know C++ well enough to
talk confidently about it, but I *believe* that a struct in C# is
roughly equivalent to a class in C++.


It has been a while, however, if I remember correctly.

In C++ there is NO difference between a class and a struct EXCPEPT
The default access qualifier for members is public for structs
The default access qualifier for members is private for classes


I thought you couldn't put methods in a struct in C++?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Apr 14 '06 #18
> C++ is somewhat different, I believe. I don't know C++ well enough to
talk confidently about it, but I *believe* that a struct in C# is
roughly equivalent to a class in C++.


I wouldn't say that. There are enough differences between the
languages, particularly where argument passing is involved, that it's
difficult to draw parallels.

C++ has nothing like C# structs. Argument passing aside, every type you
create in C++ is a reference type. If you want value semantics, or
something close to it, in C++ you use copy constructors to get that
effect. I don't recall any way in C++ to create your own type that when
declared as a local variable is allocated directly on the stack.
Someone can correct me if I'm wrong (my C++ brain cells are dying off
slowly).

The best advice I can give to C/C++ programmers coming to C# is this:
do not confuse C/C++ "struct" with C# "struct". They are completely
different animals. Forget everything you know about what "struct" means
and read the C# documentation with an open mind. Any "knowledge" you
bring with you from C/C++, where structs are concerned, can only hurt
you. At least, I kept messing them up until I decided to forget what I
"knew" and really read the doc. That's when the penny dropped.

Apr 14 '06 #19
> I don't recall any way in C++ to create your own type that when
declared as a local variable is allocated directly on the stack.


OK... maybe I'm being a dunce, here. One of my half-dead C++ brain
cells just told me that this can be done with _any_ type: just declare
a variable as being of that type rather than a pointer to that type.

Regardless, one thing I'm sure of is that in C++ classes and structs
are essentially the same thing, just that structs are sort of
"class-lite". This is absolutely not so in C#: structs act very
differently from classes, so much so that I would say that the C#
"struct" is a brand new beast that really doesn't have a parallel in
C++.

Apr 14 '06 #20
Bruce Wood <br*******@canada.com> wrote:
I don't recall any way in C++ to create your own type that when
declared as a local variable is allocated directly on the stack.
OK... maybe I'm being a dunce, here. One of my half-dead C++ brain
cells just told me that this can be done with _any_ type: just declare
a variable as being of that type rather than a pointer to that type.


Exactly - that's where I was coming from when I suggested that C#
structs were like C++ classes in some ways. Of course, you can't derive
from a C# struct, so in that sense they're totally different :)
Regardless, one thing I'm sure of is that in C++ classes and structs
are essentially the same thing, just that structs are sort of
"class-lite".
Sort of. From what I remember, structs in C++ can't have methods, so
they don't have vtables etc.
This is absolutely not so in C#: structs act very
differently from classes, so much so that I would say that the C#
"struct" is a brand new beast that really doesn't have a parallel in
C++.


Agreed.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Apr 14 '06 #21

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Bill Butler <qw****@asdf.com> wrote:
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:11**********************@v46g2000cwv.googlegr oups.com...
<snip>
> C++ is somewhat different, I believe. I don't know C++ well enough to
> talk confidently about it, but I *believe* that a struct in C# is
> roughly equivalent to a class in C++.


It has been a while, however, if I remember correctly.

In C++ there is NO difference between a class and a struct EXCPEPT
The default access qualifier for members is public for structs
The default access qualifier for members is private for classes


I thought you couldn't put methods in a struct in C++?


Sure you can.
In C you can't, but in C++...sure thing.
Actually in C you can put function pointers in structs, but they have no knowledge of *this* so they
are less useful than the C++ variant.

I am not sure why people think classes are more heavyweight than structs in C++.

Mostly due to common usage I would guess

Bill
Apr 14 '06 #22

"Jon Skeet [C# MVP]" wrote...
Bruce Wood wrote:

Regardless, one thing I'm sure of is that in C++ classes and structs
are essentially the same thing, just that structs are sort of
"class-lite".


Sort of. From what I remember, structs in C++ can't have methods, so
they don't have vtables etc.


As Bill previously said, the only difference in C++ between structs and
classes is the visibility of their members.

This is one point I usually make to programmers coming from C to C++; they
expect the same code to be compilable in either language, but they often
miss that it can result in performance hits, as when using structs they'll
be *instantiated*, running default constructors, because they're really
classes.
// Bjorn A

Apr 14 '06 #23

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Bill Butler <qw****@asdf.com> wrote:
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:11**********************@v46g2000cwv.googlegr oups.com...
<snip>
> C++ is somewhat different, I believe. I don't know C++ well enough to
> talk confidently about it, but I *believe* that a struct in C# is
> roughly equivalent to a class in C++.


It has been a while, however, if I remember correctly.

In C++ there is NO difference between a class and a struct EXCPEPT
The default access qualifier for members is public for structs
The default access qualifier for members is private for classes


I thought you couldn't put methods in a struct in C++?


Sure you can.
And you are OK with packing UNLESS you have virtual methods, a virtual base
class or multiple inheritance which introduce the vtbl pointer ( I think
that the spec may actually say that you can't rely on the layout of a class
at all for these reasons but in practice it will be the same as a struct if
you avoid the above.
Apr 14 '06 #24
On Fri, 14 Apr 2006 14:44:26 +0200, "Bjorn Abelli"
<bj**********@DoNotSpam.hotmail.com> wrote:

As Bill previously said, the only difference in C++ between structs and
classes is the visibility of their members.

Well, *again*: only nearly correct.

structs and classes differ in

1.) default visibility of members. Of course, private/protected/public
can be used in both to make the accessability whatever you want.

so, there is *no* difference between

class A
{
public:
int i;
};

and

struct A
{
int i;
};

concerning member access.


2.) default inheritance for structs is public, while for class it is
private.

so, for a type A

class B : A { ...};

means

class B : public A { ... };

if A is a struct, but means

class B : private A { ... };

if A is a class.

In C++ he class/struct does not say whether we have value or reference
semantics. ANY type in C++ can be used as value type or reference
type.

For any type T

T t; // defines a value of type T on the stack.

while

T* and T& denote reference types (pointer is considered ref
type too, here, although it really is a special case)

Hope that helps.
Martin





Apr 14 '06 #25
Bjorn Abelli <bj**********@DoNotSpam.hotmail.com> wrote:
Sort of. From what I remember, structs in C++ can't have methods, so
they don't have vtables etc.


As Bill previously said, the only difference in C++ between structs and
classes is the visibility of their members.


Righto. Good job I don't have to do much C++, isn't it? :)

Always good to keep learning...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Apr 14 '06 #26
I've sure learned a lot from this topic and for now I have enough on my
hands to master class design. As developers adopt WPF and the use of XAML it
seems to me that the struct will once again become a significant design
element.

<%= Clinton Gallagher


"Bruce Wood" <br*******@canada.com> wrote in message
news:11**********************@i40g2000cwc.googlegr oups.com...
Well, as I said in the other thread. 99.9% of the time you want a
class.

You want a struct when you want the thing to act like a primitive
type-for example, if you want to do mathematics with it-and you
don't terribly mind that it won't have any sort of identity: it will be
copied all over the place and one copy is semantically the same as any
other.

What I mean by that last bit is that, for example "customer" would make
for a lousy struct: usually you think of having one instance for each
customer, with everyone pointing at the same instance (for a single
customer). You create copies for specific reasons, like making a new
version to write back the database (as opposed to the original one you
read in, which you might be holding somewhere). You don't really think
of a customer as a "value" that is copied whenever it's assigned. Most
types you create will be like this.

However, a few things, like a Fraction (one of my value types), you
_do_ want it to act like a primitive type (the same way that decimal
acts, for example): you want to do math with it, and every time you
assign it or do some operation on it you want the result to be a copy:
you don't want to alter the number 1.5 so that every variable holding
1.5 now contains 1.7. That makes no sense. Similarly, you don't want to
modify 3 3/4 so that every variable holding it now holds 5 1/2. You
want to do some operation that results in a new value, 5 1/2, and then
store it in some variable, just the way that a decimal type works.

Take a look at the standard type System.Drawing.Point, and notice the
subtle difference between making it a class and making it a struct.

One fellow posted here that he wanted to create a drawing program that
allowed his users to place points on the screen and join them into
polygons. Then allow the user to manipulate the vertices of the polygon
on the screen. He was wondering how to do that with the standard Point
value type. The answer is that he would be better off creating a new
_class_ called Vertex, which might use Point to store its coordinates,
but which is a _class_. Why? Because if the user were to place two
vertices of two polygons at the location (4, 6), you want them to
remain distinct vertices. Since a value type has no "identity" (one
copy of (4, 6) is equivalent to any other copy of (4, 6)), this doesn't
work too well with value types. You need a class, because Vertex
objects as reference types would have _identity_: _this_ (4, 6) is
distinct from _that_ (4, 6).

By making Point a struct, MS gained some GC efficiency, but also gave
it specific semantics: Points are commodities. The only thing that
distinguishes one from another are its coordinates, its value, and if
two have the same coordinates then you can't tell whether they're
distinct points or just copies of one another. This the same as when
you have two variables containing the value 5: any distinction between
them exists only in code. There is no way that you can "mark" this
value 5 to distinguish it from that value 5. It's just 5. Classes are
different: two instances are distinct even if they contain the same
data, because they have different references (different addresses).

Anyway, you almost never want value semantics in a type you create. You
almost always want your types to have reference semantics: each
instance you create is distinct from all other instances (even if it
contains the same state, the same values in its members), and if you
want to create a copy of one you do so explicitly (via Clone).

It's only in those few cases in which you want a new type that acts
like a primitive, like int or double or DateTime, that you would use
struct.

Finally, if you do create a struct, and you think that you need it to
be mutable (you need property setters, or methods that change a value
rather than returning a new value) then you are probably abusing the
construct. This rule is not 100%: notice that Microsoft made Point
mutable, for example (you can say myPoint.X = 6), a decision with which
I don't entirely agree, by the way. The linked article showed the kinds
of (apparently) odd behaviour that can result, so I prefer immutable
structs on those rare occasions when I create one.

Apr 14 '06 #27

"Martin Aupperle" wrote...
On Fri, 14 Apr 2006 14:44:26 +0200, "Bjorn Abelli"
<bj**********@DoNotSpam.hotmail.com> wrote:

As Bill previously said, the only difference in C++ between structs and
classes is the visibility of their members.

Well, *again*: only nearly correct.

structs and classes differ in

1.) default visibility of members. Of course, private/protected/public
can be used in both to make the accessability whatever you want.


Yes, that's what I meant, but I missed to write out the little word
"default" before the word "visibility"... ;-)

// Bjorn A
Apr 14 '06 #28
"Bruce Wood" <br*******@canada.com> wrote:
Well, as I said in the other thread. 99.9% of the time you want a
class.
You want a struct when you want the thing to act like a primitive
type...


I think there's another good reason. If I do

MyClass x = obj.GetInfo();

to obtain some richly structured piece of information about "obj",
sometimes I want the recipient to know that the thing "x" they
retrieve will not change despite further changes to "obj". Structs are
the only way to tell them this in a way that's enforced by the
compiler. Otherwise, if I return a class reference, I have to just
communicate the same fact through comments.

Personally I end up wanting to do this a lot, because I come from a
functional-programming language background where it's a ubiquitous
idiom.

--
Lucian
Apr 15 '06 #29
Lucian Wischik <lu***@wischik.com> wrote:
"Bruce Wood" <br*******@canada.com> wrote:
Well, as I said in the other thread. 99.9% of the time you want a
class.
You want a struct when you want the thing to act like a primitive
type...


I think there's another good reason. If I do

MyClass x = obj.GetInfo();

to obtain some richly structured piece of information about "obj",
sometimes I want the recipient to know that the thing "x" they
retrieve will not change despite further changes to "obj". Structs are
the only way to tell them this in a way that's enforced by the
compiler. Otherwise, if I return a class reference, I have to just
communicate the same fact through comments.


Well, that only works if the struct doesn't contain any reference types
- if it does, they could still change.

Another way of doing this is to make the returned object immutable.
Immutable types are very handy, although they come with their own
problems, of course.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Apr 15 '06 #30
Jon Skeet [C# MVP] <sk***@pobox.com> wrote:
[the recipient to know that the thing "x" they retrieve will not change]

Another way of doing this is to make the returned object immutable.
Immutable types are very handy, although they come with their own
problems, of course.


How? I mean, I don't see any language support for demonstrating to the
recipient of an object that this object is immutable. Sure, you can
give them a ReadOnlyCollection<T> or an IEnumerable<T> so that *they*
can't alter it. But this doesn't assure them that *you're* not going
to alter it.

--
Lucian
Apr 15 '06 #31
> I don't see any language support for demonstrating to the recipient of an object that this object is immutable.

If its properties have no setters, and its methods don't change its
state, then it's immutable. I have many classes like this: their state
is set upon construction, and then never altered. If I want an altered
version, I have to construct a new one using the existing one as a
template.

Apr 15 '06 #32
"Bruce Wood" <br*******@canada.com> wrote:
If its properties have no setters, and its methods don't change its
state, then it's immutable.


and it's sealed.

Although... doing this, for instance, forces you to expose all details
about what you give back -- you can't give back an ICollection, for
instance.

--
Lucian
Apr 15 '06 #33
> Although... doing this, for instance, forces you to expose all details
about what you give back -- you can't give back an ICollection, for
instance.


? I'm not sure I understand? ...No, I'm quite sure I don't understand.
:-)

Could you elaborate?

Apr 16 '06 #34
> and it's sealed.

No, it doesn't even have to be sealed, so long as all fields are
private, there are no setters, and nothing is virtual, which gives
child classes no more access than the public. You could never make a
child class that altered the state of the base object, so long as you
access the properties / methods via a base class reference. Once it's
instantiated, you can't change its state.

If it's not sealed, you could create a child class that adds more
state, and that additional state may be mutable. The child class could
even hide some base class properties using "new" and make them mutable,
but only when a client is working with the child instance through a
child class reference. If you cast the reference to the base class you
will always be back to the immutable object, the way it was when it was
constructed.

Apr 16 '06 #35
"Bruce Wood" <br*******@canada.com> wrote:
Lucian wrote:
Although... doing this, for instance, forces you to expose all details
about what you give back -- you can't give back an ICollection, for
instance.


? I'm not sure I understand? ...No, I'm quite sure I don't understand.
:-) Could you elaborate?


How does a user of my object know that it's immutable? -- if I give
him just an interface to it, there's no way he can know, none at all.
Even if the object has all private fields and no methods are virtual
and there are no "setters", he still has to look at the source code or
read the comments for the object's methods to know that they won't
alter the state of the object.

--
Lucian
Apr 16 '06 #36
Bruce... ??? Classes in C++ use, by default, value semantics. In C++,
when you
declare an object, an object is created (value semantics). Hence the
need, except
in trivial cases, to write a user defined copy constructor. If you don't
write a copy
constructor, the compiler will write one for you.

Regards,
Jeff
Argument passing aside, every type you

create in C++ is a reference type<

*** Sent via Developersdex http://www.developersdex.com ***
Apr 16 '06 #37
> How does a user of my object know that it's immutable? -- if I give
him just an interface to it, there's no way he can know, none at all.
Even if the object has all private fields and no methods are virtual
and there are no "setters", he still has to look at the source code or
read the comments for the object's methods to know that they won't
alter the state of the object.


Going back to your original observation, no, there is no language
support to demonstrate that an object is immutable. It's not part of
the contract (if you will) that's stated in the C# language. It is, as
you have observed, part of the contract you make when you describe what
your class does. For better or worse, there are a lot of things not
guaranteed by the C# language itself, on which you have to trust the
person who wrote the comments.

When Jon said, "...another way is to make the returned object
immutable..." he didn't mean that you, as a consumer of a type, could
do something to guarantee that the type was immutable. Neither did he
mean that you, as the writer of a type, could do something to prove to
any consumer that it was immutable. I think that he meant "make [it]
immutable" in the sense that you write the code for the type so that
its state is established in its constructor and then no property or
method ever alters it, and then you write comments to the effect that
this type is immutable.

I'm still not sure what this has to do with properties returning
ICollections, but sometimes I can be rather thick about things.... :-)

Apr 16 '06 #38
Yeah, that's why immediately afterwards I posted that I thought maybe I
was being a dunce. I was. My apologies. :-(

Apr 16 '06 #39
"Bruce Wood" <br*******@canada.com> wrote:
Going back to your original observation, no, there is no language
support to demonstrate that an object is immutable.
My original observation was that, yes, there is language support to
demonstrate that a function returns you an "immutable" thing, in the
sense that the function will no longer alter it -- make it return a
struct! So that counts (as per thread title) of an instance "when why
and where" a struct should be used. It's for when your design calls
for something immutable by the sender, and you want it robustly
compiler-supportedly immutable against the possibility of later
programmer mistakes. (and sometimes just when the weight of putting
every single field into the constructor is too much...)

I'm still not sure what this has to do with properties returning
ICollections


I think it's interesting that, if a function returns IEnumerable<T>,
then it gives a compiler-supported guarantee that the *recipient* will
not subsequently alter the list. But it's impossible for any choice of
interface to make similar guarantees about the *sender*.

--
Lucian
Apr 16 '06 #40
Lucian Wischik <lu***@wischik.com> wrote:
"Bruce Wood" <br*******@canada.com> wrote:
Going back to your original observation, no, there is no language
support to demonstrate that an object is immutable.


My original observation was that, yes, there is language support to
demonstrate that a function returns you an "immutable" thing, in the
sense that the function will no longer alter it -- make it return a
struct! So that counts (as per thread title) of an instance "when why
and where" a struct should be used. It's for when your design calls
for something immutable by the sender, and you want it robustly
compiler-supportedly immutable against the possibility of later
programmer mistakes. (and sometimes just when the weight of putting
every single field into the constructor is too much...)


Except that if your struct contains a mutable reference type variable,
the data within that could change. It won't refer to a different
object, but the data within the object could change.

Note that using structs doesn't help when you want to return more than
one value - such as a collection. If you return an array of value
types, for instance, the array could still change contents behind the
scenes.
I'm still not sure what this has to do with properties returning
ICollections


I think it's interesting that, if a function returns IEnumerable<T>,
then it gives a compiler-supported guarantee that the *recipient* will
not subsequently alter the list. But it's impossible for any choice of
interface to make similar guarantees about the *sender*.


True. Documentation is key here, IMO.

I agree it's an issue - but it's one which hasn't proved to be too
worrying in real life, IMO. It's like the type-safety given by generic
collections - it's more useful from a confidence, automatic
documentation and value type efficiency standpoint than to actually get
rid of bugs, because in my experience there aren't many times when you
*actually* try to use something in (say) an ArrayList and choose the
wrong type.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Apr 16 '06 #41
> My original observation was that, yes, there is language support to
demonstrate that a function returns you an "immutable" thing, in the
sense that the function will no longer alter it -- make it return a struct!


True (with caveats noted by Jon). The only difficulty here is that
making something a struct changes its behaviour radically, and so yes,
you have gained a guarantee of immutability, but you've lost reference
semantics in the process. Depending upon the situation, that can be
like smashing the antique piggy bank to get at the dollar inside.

Like Jon, I've not yet run across a situation in which it was so
important to _guarantee_ immutability (in this sense) that it was worth
resorting to value semantics in order to do so. However, there is
always more to learn, and perhaps I'll run across such a situation in
the future, and I'll remember this discussion. Thanks. :-)

Apr 16 '06 #42
Bruce Wood wrote:
....
Well, yes, but there's another way that the Dispose method is called,
and that's by the garbage collector just before it reclaims an object.
So, it's not _entirely_ necessary that Dispose be called on an object
before it goes out of scope... it's just better practice because it
releases unmanaged resources sooner. (At least, that's my
understanding... someone please correct me if I'm wrong.)


Is it not Finalize method which is called by GC? To my understanding
(which can also be wrong indeed), GC does not call Dispose, so this is
still necessary to call it somehow. Normally, the call to Dispose is
placed in the object destructor for exactly this very reason: if it
was not called directly, like with 'using', it is guaranteed that it
will be called during garbage collection.
Apr 30 '06 #43
Sericinus hunter <se*****@flash.net> wrote:
Is it not Finalize method which is called by GC? To my understanding
(which can also be wrong indeed), GC does not call Dispose, so this is
still necessary to call it somehow. Normally, the call to Dispose is
placed in the object destructor for exactly this very reason: if it
was not called directly, like with 'using', it is guaranteed that it
will be called during garbage collection.


Yes, Finalize is called by the GC. The pattern is to have two Dispose
methods, one taking a boolean indicating whether it is being called via
the other Dispose method (true), or the Finalize / destructor method
(false).

And classes that own unmanaged resources *directly* are the *only*
classes which should have a finalizer.

-- Barry
Apr 30 '06 #44
On Sun, 30 Apr 2006 15:13:38 GMT, Sericinus hunter <se*****@flash.net>
wrote:
Bruce Wood wrote:
...
Well, yes, but there's another way that the Dispose method is called,
and that's by the garbage collector just before it reclaims an object.
So, it's not _entirely_ necessary that Dispose be called on an object
before it goes out of scope... it's just better practice because it
releases unmanaged resources sooner. (At least, that's my
understanding... someone please correct me if I'm wrong.)

Not true always, what about SqlConnection which lies in a connection
pool, not calling Dispose (or Close) on it will cause the connection to
remain open. It is not garbage collected as the pool hold a reference to
it so it cannot be used again.

Is it not Finalize method which is called by GC? To my understanding
(which can also be wrong indeed), GC does not call Dispose, so this is
still necessary to call it somehow. Normally, the call to Dispose is
placed in the object destructor for exactly this very reason: if it
was not called directly, like with 'using', it is guaranteed that it
will be called during garbage collection.


Finalize does not automaticaly call Dispose, but anything implementing
IDisposable should have the constructor call Dispose, or perform the
same function as Dispose (this is after all the function of the
finalizer).

From the docs on SqlConnection "If the SqlConnection goes out of scope,
it is not closed. ". This would imply to me that the finalizer for
SqlConnection does not close the underlying connection. I suppose this
must be the case as you also must not access other objects from a
finalizer (it may be that the underlying connection has been GCed
already and the wrapper is GCed after it, you cannot garuntee the order
of garbage collection).

Thus whilst finalize should clean up any unmanaged resources it cannot
do anything for managed resources. If one of those managed resources
happens to live in a pool or cache then you have the possibility of a
memory/resource leak.
Apr 30 '06 #45
Chris Chilvers wrote:
On Sun, 30 Apr 2006 15:13:38 GMT, Sericinus hunter <se*****@flash.net>
wrote:
Is it not Finalize method which is called by GC? To my understanding
(which can also be wrong indeed), GC does not call Dispose, so this is
still necessary to call it somehow. Normally, the call to Dispose is
placed in the object destructor for exactly this very reason: if it
was not called directly, like with 'using', it is guaranteed that it
will be called during garbage collection.


Finalize does not automaticaly call Dispose, but anything implementing
IDisposable should have the constructor call Dispose, or perform the
same function as Dispose (this is after all the function of the
finalizer).


Yes, that's what I was trying to say.
And I hope, by 'constructor' you actually meant 'destructor'.
Apr 30 '06 #46
> And I hope, by 'constructor' you actually meant 'destructor'.

DOH!

Heh, the new anti-pattern of constructing disposed objects, now I've
only to find a use for it...
Apr 30 '06 #47

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by sriram | last post: by
11 posts views Thread by cwdjrxyz | last post: by
9 posts views Thread by yu_sha | last post: by
3 posts views Thread by Zhigang Cui | last post: by
17 posts views Thread by Jon | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
2 posts views Thread by Marin | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.