Bookmark and Share

More On Structs

by KodefuGuru 8. June 2009 12:07

On Friday, I wrote a post that listed guidelines for when to use a struct rather than a class. A commenter of that blog entry asked me to elaborate on the 16-byte rule.

There is a special class in the .NET framework called ValueType. You can't actually inherit from this class nor can you use it as a generic constraint, but you can use it for variable and parameter declarations when you don't want to accept a reference type. There are two type of constructs that inherit from this class: structs and enums.

        static void Main(string[] args)
        {
            
//It will accept structs
            ParameterTest(0);
            
//It will accept enums
            ParameterTest(TypeCode.Boolean);
            
//It won't accept reference types
            ParameterTest("This line doesn't work");
        }

        
static void ParameterTest(ValueType value)
        {
            
Console.WriteLine(value);
        }

Unlike other objects (referred to as reference types), value types go on the stack rather than the heap. The benefits of using the stack are that operations on it are faster, the disadvantage is that there's less memory. Despite the shortage of memory, it isn't going to be an issue the majority of the time unless you're creating tons of these objects. What is an issue is the immutable nature of value types. Every time a modification is made to the object, it creates a new one. Every time you pass the object to a method, it creates a new one. With a large struct, this can be an issue with the default 1 MB you have for the stack. It's also likely that 32-bit processors' operations can handle 16 bytes of memory better than larger sizes, but I lack the expertise on processors to definitively make this claim. If this is the case, 64-bit processors will better handle larger structs.

I am opposed to creating structs with reference type members, and for this reason I'm opposed to creating structs wth string members. Reference members indicate that the value type doesn't really represent a "value." However, if you were to include one it would take up as much space as the reference to the heap takes up. In the case of the Address example in the prior post, the struct size would be 20 bytes - 4 bytes per string on a 32-bit processor.

If you include an mutable reference type as a member on a struct, you run into another problem. The rules of mutability no longer apply, as the reference will still refer to the same memory location.

    class Program
    {
        
static void Main(string[] args)
        {
            
Test test = new Test(1);
            Change(test);

            
//Writes 9 to the screen
            Console.WriteLine(test.ReferenceType.Number);
        }

        
static void Change(Test test)
        {
            test.ReferenceType.Number = 9;
        }
    }

    
struct Test
    {
        
private ReferenceType referenceType;

        
public ReferenceType ReferenceType
        {
            
get { return referenceType; }
            
set { referenceType = value; }
        }

        
public Test(int a)
        {
            referenceType =
new ReferenceType();
            referenceType.Number = a;
        }
    }

    
class ReferenceType
    {
        
public int Number { get; set; }
    }

In this example, the constructor had originally set ReferenceType.Number to 1. The method Change() sets ReferenceType.Number to 9. Since that ReferenceType is a reference, the memory location on the heap has been modified. Therefore, the change will be reflected in the Console.WriteLine() statement. Despite being a value type and the variable in Change() being a copy of the variable in Main(), the semantics of Test have changed to be partly mutable.

Tags:

Kodefu

blog comments powered by Disqus

KodefuGuru.GetInfo()

Chris Eargle
LinkedIn Twitter Technorati Facebook

Chris Eargle
C# MVP, INETA Community Champion


MVP - Visual C#

 

INETA Community Champions
Friend of RedGate
Telerik .NET Ninja
Community blogs & blog posts

I am a #52er

I have joined Anti-IF Campaign


World Map

Tag cloud

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010