13

To use a struct, we need to instantiate the struct and use it just like a class. Then why don't we just create a class in the first place?

user133466
  • 3,391
  • 18
  • 63
  • 92

9 Answers9

19

A struct is a value type so if you create a copy, it will actually physically copy the data, whereas with a class it will only copy the reference to the data

Paul
  • 9,409
  • 13
  • 64
  • 113
  • 3
    (Until you embed a reference type in your struct - in which event it will only copy the reference to that object) – Robert Venables Aug 01 '09 at 17:10
  • 3
    Novatrust, that is not an exception to what IP describes. – H H Aug 01 '09 at 17:12
  • The value of a reference type is the reference itself, so that's to be expected. I've yet to find a good way to describe this without it sounding confusing :( – Mark Simpson Aug 01 '09 at 17:14
  • 1
    True, but it's a valid clarification. Wrapping references in a struct does not magically create deep copies. – Steven Sudit Aug 01 '09 at 17:14
  • 3
    For you and I, but for someone with has a weak understand of a value and reference types it is an important distinction. – Robert Venables Aug 01 '09 at 17:15
  • @novatrust: IP's statement is correct. The value of a reference type is the reference, not the referent. – jason Aug 01 '09 at 17:18
8

A major difference between the semantics of class and struct is that structs have value semantics. What is this means is that if you have two variables of the same type, they each have their own copy of the data. Thus if a variable of a given value type is set equal to another (of the same type), operations on one will not affect the other (that is, assignment of value types creates a copy). This is in sharp contrast to reference types.

There are other differences:

  1. Value types are implicitly sealed (it is not possible to derive from a value type).
  2. Value types can not be null.
  3. Value types are given a default constructor that initialzes the value type to its default value.
  4. A variable of a value type is always a value of that type. Contrast this with classes where a variable of type A could refer to a instance of type B if B derives from A.

Because of the difference in semantics, it is inappropriate to refer to structs as "lightweight classes."

jason
  • 236,483
  • 35
  • 423
  • 525
  • "two variables of the same type, they each have their own copy of the data"...isn't that the same as var x = new SomeClass() and var y = new SomeClass()? They would both have their own copy of the data. –  Oct 18 '10 at 05:02
  • 3
    @Vince: Look at it like this. If you have `var x = new SomeClass();` and `var y = x;` then mutating `x` will mutate `y`. But if you have `var x = new SomeStruct();` and `var y = x;` this is not the case. – jason Oct 18 '10 at 05:23
7

All of the reasons I see in other answers are interesting and can be useful, but if you want to read about why they are required (at least by the VM) and why it was a mistake for the JVM to not support them (user-defined value types), read Demystifying Magic: High-level Low-level Programming. As it stands, C# shines in talking about the potential to bring safe, managed code to systems programming. This is also one of the reasons I think the CLI is a superior platform [than the JVM] for mobile computing. A few other reasons are listed in the linked paper.

It's important to note that you'll very rarely, if ever, see an observable performance improvement from using a struct. The garbage collector is extremely fast, and in many cases will actually outperform the structs. When you add in the nuances of them, they're certainly not a first-choice tool. However, when you do need them and have profiler results or system-level constructs to prove it, they get the job done.

Edit: If you wanted an answer of why we need them as opposed to what they do, ^^^

Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • blitting structs from an unmanaged buffer is awesome for performance :) – ShuggyCoUk Aug 01 '09 at 21:20
  • Some kinds of things are best described as fixed set of independent values; operations on them will focus on two basic operations: set one property of a storage location equal some value, or make all properties of one location match those of another. Unshared mutable classes are good at the first, but bad at the second. Sharable immutable classes are bad at the first, but excellent at the second. Exposed-field structures are excellent for the first and decent at the second. So-called immutable structs are bad at the first and decent at the second. – supercat Aug 28 '13 at 20:14
  • Rather than saying "one will rarely see a performance improvement from using a struct", it would be helpful to know what types of structs are being compared with what types of classes, and what the usage pattern is. Note also that in scenarios where neither of the two aforementioned operations dominates, the performance advantages of structures *increase with size* until they get so big as to blow the stack. It's only when the second operation dominates that large class objects substantially outperform large structures. – supercat Aug 28 '13 at 20:17
6

In C#, a struct is a value type, unlike classes which are reference types. This leads to a huge difference in how they are handled, or how they are expected to be used.

You should probably read up on structs from a book. Structs in C# aren't close cousins of class like in C++ or Java.

nagul
  • 2,243
  • 2
  • 19
  • 21
3

This is a myth that struct are always created on heap. Ok it is right that struct is value type and class is reference type. But remember that

1. A Reference Type always goes on the Heap.
2. Value Types go where they were declared.

Now what that second line means is I will explain with below example

Consider the following method

  public void DoCalulation()
  {
        int num;
        num=2; 
  }

Here num is a local variable so it will be created on stack.

Now consider the below example

public class TestClass
{          
    public int num;
}
public void DoCalulation()
{
    TestClass myTestClass = new TestClass ();
    myTestClass.num=2;
}

This time num is the num is created on heap.Ya in some cases value types perform more than reference types as they don't require garbage collection.

Also remeber:

The value of a value type is always a value of that type. The value of a reference type is always a reference.

And you have to think over the issue that if you expect that there will lot be instantiation then that means more heap space yow will deal with ,and more is the work of garbage collector.For that case you can choose structs.

Raghav
  • 8,772
  • 6
  • 82
  • 106
1

the difference is that a struct is a value-type I've found them useful in 2 situations

1) Interop - you can specify the memory layout of a struct, so you can guarantee that when you invoke an unmanaged call.

2) Performance - in some (very limited) cases, structs can be faster than classes, In general, this requires structs to be small (I've heard 16 bytes or less) , and not be changed often.

Jimmy
  • 89,068
  • 17
  • 119
  • 137
  • Exposed-field structures offer their biggest performance advantages in cases when the frequency of two operations is within a couple orders of magnitude: (1) copy the state encapsulated by one variable to another; (2) modify part of the state encapsulated in a variable. The only classes which can do #1 more efficiently than a struct of any size are immutable classes, and immutable classes are very bad at #2 (the larger the class, the worse the performance). In cases where structs are usable, they'll outperform classes unless one of those ops is so rare that its performance is a non-factor, – supercat Jun 01 '14 at 21:41
1

One of the main reasons is that, when used as local variables during a method call, structs are allocated on the stack.

Stack allocation is cheap, but the big difference is that de-allocation is also very cheap. In this situation, the garbage collector doesn't have to track structs -- they're removed when returning from the method that allocated them when the stack frame is popped.

  • edit - clarified my post re: Jon Skeet's comment.
Mark Simpson
  • 23,245
  • 2
  • 44
  • 44
  • 3
    Structs are allocated "inline" with the variable. That *may* be on the stack, or it may be on the heap if it's part of another object. – Jon Skeet Aug 01 '09 at 17:01
  • True, I was coming from the perspective of local variables :) (e.g. doing a calculation in a method using several local variables). I should've clarified this. – Mark Simpson Aug 01 '09 at 17:04
  • This refers to implementation detail and not semantical differences between "class" and "struct." – jason Aug 01 '09 at 17:10
  • 1
    The question he asked is "Why do we need struct?". My answer contains a valid and practical point -- structs are cheaper to de-allocate compared to classes as the GC doesn't have to track them. When writing a simple type that will be instantiated thousands of times in a short period of time, you'll likely care about this difference. In some cases, implementation details matter. – Mark Simpson Aug 01 '09 at 17:21
  • 1
    First, there is no guarantee that structs will henceforth be allocated on the stack; this is not part of the language specification. The JITter can allocate the struct anywhere it pleases so long as it observes the value semantics of structs. Second, we need structs not for the performance difference (as currently implemented) but for the value semantics that they provide. Third, the choice of using structs versus classes should only be made after profiling. Most of the time the choice should be made on the basis of whether we want value semantics of reference semantics. – jason Aug 01 '09 at 17:51
  • 1. I seriously doubt that's going to change. 2. That's one reason why structs are needed; it's not the only reason. 3. I agree. We indeed have just had a situation at work where we profiled and found it made sense to replace various classes with structs. – Mark Simpson Aug 01 '09 at 17:58
1

Structs have many different semantics to classes. The differences are many but the primary reasons for their existence are:

  1. They can be explicitly layed out in memmory
    • this allows certain interop scenarios
  2. They may be allocated on the stack
    • Making some sorts of high performance code possible in a much simpler fashion
ShuggyCoUk
  • 36,004
  • 6
  • 77
  • 101
-1

A struct is a value type (like Int32), whereas a class is a reference type. Structs get created on the stack rather than the heap. Also, 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.

If you need to create your own datatype, say, then a struct is often a better choice than a class as you can use it just like the built-in value types in the .NET framework. There some good struct examples you can read here.

Dan Diplo
  • 25,076
  • 4
  • 67
  • 89
  • 2
    "Structs get created on the stack rather than the heap" not always - don't parrot this it is much ore subtle. also you should say a _copy_ of a reference is passed. – ShuggyCoUk Aug 01 '09 at 17:01
  • Besides, this is merely an implementation detail. – Robert Venables Aug 01 '09 at 17:02
  • 1
    Take it up with Microsoft, then, since this is what MSDN says: "When you call the New operator on a class, it will be allocated on the heap. However, when you instantiate a struct, it gets created on the stack." - http://msdn.microsoft.com/en-us/library/aa288471(VS.71).aspx – Dan Diplo Aug 01 '09 at 17:05
  • novatrust: "Besides, this is merely an implementation detail." Yes, it is an implementation detail, but it's an important detail in some situations. – Mark Simpson Aug 01 '09 at 17:10
  • structs and other value-types get created on the heap all the time, inside objects or arrays. – H H Aug 01 '09 at 17:23
  • I see the Karma Police are out in force today. – Dan Diplo Aug 01 '09 at 17:49
  • @Dan: MSDN used to claim that Decimal was a fixed point type. Sometimes MSDN is wrong. It is in this case. – Jon Skeet Aug 01 '09 at 18:13
  • Yeah - my boss was amazed when I told him how Decimal actually worked. Also the latest x86 JIT may entirely enregister a struct or a class, which is neither the stack nor heap... the important aspect is the copy semantics, not the location in memory. as nova so correctly states, "it's implementation" not specification. MSDN is wrong far too often, when it's right it's great. – ShuggyCoUk Aug 01 '09 at 21:25
  • @Jon - Not all of us are born with an intimate knowledge of the CLR therefore we rely on documentation. I'm happy to learn new things, but the rather smug and patronising attitudes exhibited here (being told I'm "parroting" etc.) makes me wonder whether I'll bother in future. – Dan Diplo Aug 02 '09 at 09:12
  • @Dan: With all due respect, this might be one of those places where you might do well to grow a thicker skin with regard to constructive criticism. – Steven Sudit Aug 03 '09 at 03:56
  • @Steven - I have no problem with constructive criticism, just rudeness. Constructive criticism is were you point out politely why somebody is wrong, provide a useful reference to back up your point and don't do so in an overtly smug or patronising manner. I had thought that StackOverflow was a little bit classier than most forums in that regard. – Dan Diplo Aug 03 '09 at 08:42
  • @Dan: Like everything else, it varies. Some criticisms are politer than others, and people's tolerance for directness also varies, so there's bound to be a few ruffled feathers sooner or later. That's why I prefer to focus on the content rather than the tone. What makes criticism constructive isn't whether it's polite, but rather whether it helps. In this case, you got downvoted because you repeated a common misconception. I would not have downvoted you, myself. In fact, I just upvoted strategically. However, your answer was incorrect, so it's good that it was rejected. – Steven Sudit Aug 03 '09 at 14:49
  • @Dan comment textboxes are small - I tend to get to the point with this since it this is an oft made error. Structs can be created in far more ways than with new. If you are going to tell put your views out there the onus is on you to make sure you are right, expect to be told when you're wrong (we all are at some point) learn from it and become better. If you repeat what you read/hear without understanding it or critiquing it then you are parroting, sorry if this offends but it is true. – ShuggyCoUk Aug 03 '09 at 17:41
  • As an aside I didn't actually -1 your question, though if you like I can and then your delete would get you a peer pressure badge. – ShuggyCoUk Aug 03 '09 at 17:42
  • Thanks for your comments - I understand and respect what you are saying. I am not at all bothered about points or being down voted. But... it doesn't take much more effort to correct someone in a polite manner than it does in a derisory one. I also think it's useful to say more than, "You're wrong" - provide an explanation or link to back this up (especially when making claims that MSDN is incorrect!) so that people can learn from and understand *why* it is wrong. That way new members aren't entirely put off contributing in the future and people can genuinely learn from their mistakes. – Dan Diplo Aug 03 '09 at 18:46
  • if you want a decent link on why Jon Skeet's article goes in depth but is very interesting: http://www.yoda.arachsys.com/csharp/memory.html – ShuggyCoUk Aug 04 '09 at 09:25