views:

425

answers:

3

I get an error when I compile this code:

using System;

public struct Vector2
{
    public event EventHandler trigger;

    public float X;
    public float Y;

    public Vector2 func()
    {
        Vector2 vector;
        vector.X = 1;
        vector.Y = 2;
        return vector;  // error CS0165: Use of unassigned local variable 'vector'
    }
}

hi!

The compiler says: "Use of unassigned local variable 'vector'" and points to the return value. It looks to me that Vector2 become a reference type (without the event member it acts normally). What is happening?

+13  A: 

In C# you still need to 'new' a struct to call a constructor unless you are initializing all the fields. You left EventHandler member 'trigger' unassigned.

Try either assigning to 'trigger' or using:

Vector2 vector = new Vector2()

The new object is not allocated on the heap, it is still allocated on the functions stack.

To quote MSDN:

When you create a struct object using the new operator, it gets created and the appropriate constructor is called. Unlike classes, structs can be instantiated without using the new operator. If you do not use new, the fields will remain unassigned and the object cannot be used until all of the fields are initialized.

Rob Walker
You should be able to initialize it to null
Robert Wagner
I like to initialize my events to '= delegate { };', so I don't have to null-check when firing the event.
Jay Bazuzi
+1  A: 

Rob Walker has a better response, since he started from the docs and then reasoned to the code (whereas I went the other way around).

If you compile the sample code with the trigger field commented out, and then run IlAsm to get the resulting MSIL, you'll see that there is no initobj opcode for the local variable vector.

The lack of initobj is fine when the Vector2 structure only contains value types. They're just raw memory after all. However, if the Vector2 structure also contains a reference, it must be initialized in order to prevent having an uninitialized object reference.

In order to avoid returning a partially unitialized object, you need to write to the trigger event handler explicitly, or initialize the whole object by way of a new operation. However, in no case is the structure turned into a reference type.

Kennet Belenky
+2  A: 

Others have explained ways round this, but I think it's worth mentioning the other big, big problem with your code: you have a mutable struct. Those are pretty much always a bad idea. This is bound to be just the first of many issues you'll run into if you keep it that way.

I strongly recommend that you either make it immutable or make it a class.

Jon Skeet
I'll emphatically second that - mutable structs *always* cause more pain than people expect.
Marc Gravell