ARTICLE

Structs in C#

Posted by Shashi Ray Articles | C# Language September 25, 2008
This article introduces struct types in C# and .NET Framework.
Reader Level:

This article introduces you to the differences between classes and structs in C#, and explains how to use structs correctly.  

Why we need Structs?

 

The basic reason is the ability to create types with value semantics, which, if properly used, leads to better performance in a managed environment. 

.NET supports the notion of value types and reference types. Instances of reference types get allocated in the managed heap and are garbage collected when there are no outstanding references to them. Instances of value types, on the other hand, are allocated in the stack, and hence allocated memory is reclaimed as soon as their scope ends. All C# primitive data types, except for System.String, are value types.

In C#, structs are value types, classes are reference types. There are two ways you can create value types, in C#, using the enum keyword and the struct keyword. Using a value type instead of a reference type will result in fewer objects on the managed heap, which results in lesser load on the garbage collector (GC), less frequent GC cycles, and consequently better performance. However, value types have their downsides too. Passing around a big struct is definitely costlier than passing a reference, that's one obvious problem. The other problem is the overhead associated with boxing/unboxing. Apart from performance, there are times when you simply need types to have value semantics, which would be very difficult to implement if reference types are all you have.

Differences between Class & Struct:

 

  1. Struct and Inheritance

structs derive from System.ValueType whereas classes derive from System.Object or one of its descendants. Of course, System.ValueType again derives from System.Object, but that's beside the point. structs cannot derive from any other class/struct, nor can they be derived from. However, a struct can implement any number of interfaces. Although, that when you treat the struct as an interface, it gets implicitly boxed, as interfaces operate only on reference types. E.g.

 

struct Fun : IFun

      {

                  int x;

      }

and then:

IFun iFun = new Fun();

an instance of Foo is created and boxed. All interface method calls then execute only on the boxed instance.

  1. Constructors:

Although the CLR allows it, C# does not allow structs to have a default parameterless constructor. The reason is that, for a value type, compilers by default neither generate a default constructor, nor do they generate a call to the default constructor. So, even if you happened to define a default constructor, it will not be called and that will only confuse you. To avoid such problems, the C# compiler disallows definition of a default constructor by the user. And because it doesn't generate a default constructor, you can't initialize fields when defining them, like:

                        struct MyWrongFun

                        {          

                                    int x = 1;

                        }

The compiler puts all this initialization code into the constructor (every constructor), and because there's no default constructor, you can't do the initialization.

  1. Destructors:

You cannot define destructors for structs. The compiler straightaway flags it as an error. Of course, structs can implement IDisposable (it being an interface), so you can always use the dispose pattern (with the extra boxing overhead).

When to use Structs?

 

  • You want your type to look and feel like a primitive type.
  • You create a lot of instances, use them briefly, and then drop them. For e.g., within a loop.
  • The instances you create are not passed around a lot.
  • You don't want to derive from other types or let others derive from your type.
  • You want others to operate on a copy of your data (basically pass by value semantics).

 

When not to use Structs?

 

  • The size of the struct (the sum of the sizes of its members) gets large. The reason is that beyond a particular size, the overhead involved in passing it around gets prohibitive. Microsoft recommends that the size of a struct should ideally be below 16 bytes, but it really is up to you. In case your struct has reference types as members, make sure you don't include the size of instances of reference types, just the size of the references.
  • You create instances, put them in a collection, iterate and modify elements in the collection. This will result in a lot of boxing/unboxing as FCL Collections operate on System.Object. Every addition will involve a boxing operation, and every modification will involve an unboxing followed by a boxing operation.

 

Login to add your contents and source code to this article
post comment
     

hi i am NavinKumar from chennai,
i am an entry level .net developer. i like to some basics in .net. Where as i am working with silverlight.net in a private concern in chennai. can you please help me to know some more in .net. If you can please reply to my mail id ksnavinkumar@live.com 

Posted by Navin Kumar May 25, 2010

test

Posted by Mohammed Kharboush Sep 27, 2008

the default implementation of Object.Equals for value types (struct) uses reflection to get all the fields for the 2 objects and then retrieve value for them then compare them. For reference type it just compare the reference of the two object.

Specific to C# - the default layout of fields for reference is LayoutKind.Auto and for structures/value types it's LayoutKind..Sequential

Thanks & Regards,
Ashutosh Bhawasinka

Posted by Ashutosh Bhawasinka Sep 26, 2008
COMMENT USING
PREMIUM SPONSORS
Over-C is a holistic consortium of communications and technology specialists. We build, deploy and market both business as well as consumer products and solutions.
Get Career Advice from Experts
SPONSORED BY
  • PDF reports have never been easier to create. With our included WYSIWYG Designer, you can layout your reports, set up your data source and let DynamicPDF ReportWriter do the rest.
Join a Chapter