Class or struct

  • Thread starter Kenneth Siewers Møller
  • Start date
K

Kenneth Siewers Møller

Hi there

I know this probably have been addressed before, but I have an object that
should contain the following
Guid id
String fName
String lName

Could I use a struct for that? I have read that a struct should only contain
valuetypes and should be below 16byte in memory size. The guid is actually
16 byte in size but can i use string (which are ref-types) in my struct?

The problem is that I have an array of customers that I need to transfer in
a WebService. I could of course create a two-dimentional array or use a
class, but what is the best practice or choice for that matter?

Thanks in advance...
 
R

randolpho

Chris' link was very interesting (and has been saved -- there was some
good stuff in there!), but let me boil it down for you:

Structs are value types. They're instantiated on the stack. Classes are
reference types. They're instantiated on the heap. The bottom line is
that you should use a struct only when you *want* value type semantics.
If you pass the struct to a method for whatever reason, do you want the
original struct given to the method, or do you want a copy? If you use
a struct, you are passing a copy of the struct to the method, rather
than a reference to the original struct to the method. If that's what
you want, use a struct. The reason structs should be limited in size is
because of that copying behavior.

To answer your specific question, yes, you can use strings in a struct,
and no, it's not that big a deal. Strings are reference types, yes, but
the upshot of that that is that if you use a string in a struct you are
only adding 4 bytes to the size of your struct. The actual memory for
the string is stored in the heap; you're just storing the reference in
the struct. So the struct you gave as an example would be 24 bytes
large when stored in memory on the stack. Not *too* big, so it wouldn't
be a major performance hit as a struct if you're doing a lot of method
calls.

As for transferring to the web wervice... if it's a .NET web service,
you can easily serialize either a class or a struct, and passing it to
the web service will be roughly the same in terms of size. The choice
of struct or class in that case is basically irrelevant.
 
J

Jon Skeet [C# MVP]

Chris' link was very interesting (and has been saved -- there was some
good stuff in there!), but let me boil it down for you:

Structs are value types. They're instantiated on the stack.

That's not quite true. The data lives wherever the variable it's held
by lives (if it's in a variable). For instance, a value type variable
in a reference type will still live on the heap.

See http://www.pobox.com/~skeet/csharp/memory.html for more about this.

Jon
 
R

randolpho

That's a good point, and shame on me for not being more specific. I
meant that when a struct is instantiated within code, i.e. within a
method, it's instantiated on the stack, just like other value types.

E.g.

struct foo
{
int bar;
}

class example
{
public static void Main()
{
foo x = new foo(); // the foo struct named "x" is instantiated on
the stack.
}
}
 
M

Michael Nemtsev

Hello Chris,

CF> This article outlines some of the differences between C# classes and
CF> structs:
CF> http://www.jaggersoft.com/pubs/StructsVsClasses.htm

One note that was missed in this article is that u can be careful with returning
structs from the method/property.
C# doesn't support returning by ref and we get copy of the structure, not
the initial stuct

---
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
 
B

Bruce Wood

One of my rules of thumb is that as soon as you see some sort of UID
involved, you need a class. Here is my reasoning.

If something has a UID, then you typically want to refer to a single
copy of it, and make a duplicate only upon demand, because you
logically think of "that customer there" as opposed to "this customer
here". You may choose to clone it in order to create multiple versions
(the customer as it is in the database versus the changed customer to
be written to the database), but this is a conscious decision...
something that you do explicitly as part of your system design.

If you designed your system so that an item with a UID were copied
everywhere, I think that you (and other programmers coming after you)
would find the design difficult to follow: constantly having to
remember that there may be dozens or hundreds of copies of this
customer floating around in memory.
From the other side, things with value semantics usually have no unique
identifier. An "int" has no UID... it could serve as a UID for some
other type, but it itself does not have one. That's why copying it on
every call and every method return is not a problem: because there is
no need to distinguish between "this number 5" and "that number 5". The
value is all that matters.

The same goes for Point and Rectangle, by the way, two popular value
types in the .NET Framework: there is no concept of "this Point" versus
"that Point" if the two have the same coordinates.

So, in your case, I would definitely not make your customer a struct. I
would definitely make it a class, even if it were smaller than 16 bytes.
 
N

Nick Hounsome

Chris' link was very interesting (and has been saved -- there was some
good stuff in there!), but let me boil it down for you:
[cut]

To answer your specific question, yes, you can use strings in a struct,
and no, it's not that big a deal. Strings are reference types, yes, but
the upshot of that that is that if you use a string in a struct you are
only adding 4 bytes to the size of your struct. The actual memory for
the string is stored in the heap; you're just storing the reference in
the struct. So the struct you gave as an example would be 24 bytes
large when stored in memory on the stack. Not *too* big, so it wouldn't
be a major performance hit as a struct if you're doing a lot of method
calls.

Note that the absense of a user defined default destructor pretty much
forces you to use to put extra code in your and properties to access
reference types if you don't want unexpected nulls:

struct S
{
private string name;
// public S() { name = "Dilbert"; } // Cannot do this!
public S(string name) {this.name = name;}
public string Name { get { return name == null ? "Dilbert" : name; }}
}
 

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