4

As it says on MSDN documentation and elsewhere, a struct has no identity and should therefore represent an "eternal" value that never changes, eg a phone number (the phone number doesn't change, but you get a new one).

How can this influence my coding decisions?

Based on that knowledge, am I right in thinking that no identity means that if two structs have the same data, there is no way to tell them apart, so conceptually, they are the same thing. So two structs used in a codebase for a number for example (7) are always the same thing. So with classes, two objects with the same data (e.g. a person object with just name) can be different people, yet with structs, this distinction does not exist. So a struct that may represent a skill (e.g. fishing) will always be the same (there is no identity to distinguish it).

Hope that makes sense.

Thanks

GurdeepS
  • 65,107
  • 109
  • 251
  • 387
  • 2
    I'm really not following your assortment of metaphors... But you might be interested to read about the differences between classes and structs as types within the language: http://msdn.microsoft.com/en-us/library/ms173109.aspx Most importantly is that classes are reference types (pointers to values in the heap) while structs are value types (primitive values on the stack). – David May 19 '12 at 13:07
  • 2
    @David structs are not necessarily stored on the stack – David Heffernan May 19 '12 at 13:13
  • @DavidHeffernan: Interesting, I guess I should read up on it as well. (I also just noticed that I used the word "classes" where "objects" or "instances" would have been more appropriate.) The main point is to know that there are differences and to research those differences. I'm still trying to make sense of the metaphors in the question, though. Maybe he's talking about immutability? Not sure. – David May 19 '12 at 13:17
  • 1
    It's simple. Ask yourself how you tell the difference between two ints. – John Saunders May 19 '12 at 13:17
  • To use a crude analogy, think of a class-type storage location as being a slip of paper than can hold a car's Vehicle Identification Number, whereas a struct holds a car. If one hands a paint shop a slip of paper and asks them to paint the car identified by that paper, that may also change the color of the car identified by any other slip of paper which identifies the same car. By contrast, if one paints a car stored in one garage, that will not affect the color of any car in any other garage. In .net, for various practical reasons, structs can't contain things as complicated as... – supercat May 20 '12 at 04:22
  • ...the things classes can refer to, but the key idea--the fact that making a a change to struct in one storage location will not affect the one stored in others--applies just fine. Note that copying a class-type storage location makes a copy of an ID number, while copying a struct-type storage location duplicates the actual thing that's there. – supercat May 20 '12 at 04:23

3 Answers3

4

Structs share most of the same syntax as classes, but according to MSDN:

The struct type is suitable for representing lightweight objects

The key difference between them is that Classes generate reference-type objects while Structs generete value-type objects, which means that the following operation:

Point A = new Point();
Point B = A;

Will make A and B access the same in-memory object if Point is a Class, or create a new copy of A and assign it to B if Point is a Struct.

In the case Point is a Struct, the following relations hold:

Object.Equals(A,B) == true
Object.ReferenceEquals(A,B) == false

Hence you can tell them apart, and the two structs are not the same thing because each one of them is an object in memory.

This SO question discusses when it is a good idea to use Structs.

Community
  • 1
  • 1
Thomas C. G. de Vilhena
  • 13,819
  • 3
  • 50
  • 44
  • *Structs and Classes behave very similarly* ...did this come from a source or did you say this? I'm not inclined to agree at all. Otherwise, good answer. – IAbstract May 19 '12 at 14:35
  • That is something I wrote (didn't come from a source) because Structs inherit from the base class Object, thus their underlying behaviour is similar to that of Classes. I also wrote that because one can define Constructors, Methods and Properties for Structs the same way it's done for Classes. – Thomas C. G. de Vilhena May 19 '12 at 15:05
  • Instantiation behavior is key between structs and classes. Yes, a value type (as all types do) inherits from object implicitly. A struct is instantiated on the stack (moved to heap if cast to interface - thus now behaving like a ref type); a class is instantiated on the heap. A struct (like a class) implies a public parameterless constructor - although, if you have fields defined in the struct, you must assign values in the ctor. These are just a few of the difference - and they're significant enough for me to disagree with the generality that *Structs and Classes behave very similarly*. :) – IAbstract May 19 '12 at 16:15
  • All right, you convinced me! I have edited my answer to make that statement less generic. :) – Thomas C. G. de Vilhena May 19 '12 at 18:01
  • Internally, defining a struct actually defines two types: a value type, and a heap-object-reference type inherited from class `ValueType`. A widening conversion exists from the value type to its corresponding reference type. Storage locations of struct type always hold value-type instances. Storage locations of reference type (e.g. `Object`) always hold heap-object references. An instance of `List.Enumerator` which is stored in a variable or field of that type will behave as a value type; one stored in a variable or field of type `IEnumerator` will behave as a class object. – supercat May 21 '12 at 18:06
  • The C# standard defines "inheritance" in such a way that all value types inherit from `Object`, but I think it's more useful to define inheritance more narrowly, such that if `X` inherits from `Y`, there is an *identity-preserving* widening conversion from `X` to `Y`. By that definition, boxed value types (i.e. instances of the value type's associated heap-object type) inherit from `Object`, but non-boxed ones do not. – supercat May 21 '12 at 18:09
1

A struct is a value. A class is an object. It is very similar to real life, where 42 will always equal 42, but you can have two people by the name of John Smith.

What you said in the question is a very good outline of the concepts of value types vs. reference types.

As for how it should influence your coding, always code so that a value will equal an identical value, e.g. 42 must always equal 42. There are some cases where a reference type should be compared by value instead of identity (e.g. string). But in the majority of cases, reference types compare by identity.

If you can measure or calculate it, it belongs in a value type. Otherwise, use a reference type.

Kendall Frey
  • 43,130
  • 20
  • 110
  • 148
  • I see, thanks. Can you explain the "reference types go by identity" sentence? I keep thinking identity is like a GUID or something? – GurdeepS May 19 '12 at 14:18
  • Identity is what differentiates one object from another. In C#, 'identity' happens to correspond with 'location in memory'. An object's memory address can be considered its identity. Also read: http://en.wikipedia.org/wiki/Identity_(object-oriented_programming) – Kendall Frey May 19 '12 at 14:27
  • Excellent link, I didn't know there was an article for that on wikipedia! – GurdeepS May 19 '12 at 21:11
0

The "struct" or "record" concept was created before the "class" concept. And sometimes, can be interchanged.

When to use a variable, field or instance of an struct:

(1) When Only Data members are need it, without methods. Or has few methods, that are barely used, such as constructors.

Example:

struct CoordinateStruct
{
  int X;
  int Y;
}

(2) When a great quantity of elements, are required, and since objects, use additional memory, sometimes not visible, migrating methods to a container element, such another object, a module (namespace) like object, or singleton object (Flyweight design pattern).

Before:

class PointClass
{
  int X;
  int Y;
  // its also an object / class
  Color Color;

  public void assign(int NewX, int NewY, Color NewColor) { ... }
  public void move(int addX, int addNewY) { ... }
}

// multiple element container
class CADAppClass
{
  List<Point> Points;

 // ...
}

// Not enough memory Exception !!!

After:

struct PointStruct
{
  int X;
  int Y;
  // its a low memory integer
  int Color;      
}

// multiple element container
class CADAppClass
{
  List<Point> Points;

  public void assignPoint
    (ref PointStruct Point, int NewX, int NewY, Color NewColor) { ... }
  public void movePoint
    (ref PointStruct Point, int addX, int addNewY) { ... }

 // ...
}

(3) When you need to encapsulate the data elements, even if its a small quantity of elements, in a variable, even if there are methods, operators, events or "messages". The encapsulation, maybe for serializacion as an example (loading from D.L.L., DCOM, JSON, plain data files).

Before:

class CustomerClass
{
  String FirstName;
  String LastName;

  public void Store(Stream Destination) { ... }
  public void Load(Stream Source) { ... }

  public void CopyTo(CustomerClass Destination) { ... }
  public void CopyFrom(CustomerClass Source) { ... }
}

After:

struct CustomerStruct
{
  char[100] FirstName;
  char[100] LastName;
}

// one to one, nested, relationship, seems redudant,
// but required
Class CustomerClass
{
  CustomerStruct Data;

  public void Store(Stream Destination) { ... }
  public void Load(Stream Source) { ... }

  public void CopyTo(CustomerStruct Destination) { ... }
  public void CopyFrom(CustomerStruct Source) { ... }
}

I used this one, with enumerations, instead of structs, in programming languages that are Object & Class Oriented, but, that doesn't treat enumerations as objects (Example: Object Oriented PHP & Object Pascal), as Java or C#, does.

(4) A mix of the previous cases, or a scenario, not considerated.

Cheers.

umlcat
  • 4,091
  • 3
  • 19
  • 29