views:

125

answers:

4

Hi. This is simple to explain: this works

using System;
using ConstraintSet = System.Collections.Generic.Dictionary<System.String, double>;

namespace ConsoleApplication2
{
    class test
    {
        public ConstraintSet a { get; set; }
        public test()
        {
            a = new ConstraintSet();
        }
        static void Main(string[] args)
        {
            test abc = new test();
            Console.WriteLine("done");
        }
    }
}

this does not

using System;
using ConstraintSet = System.Collections.Generic.Dictionary<System.String, double>;

namespace ConsoleApplication2
{
    class test
    {
        public ConstraintSet a { get { return a; } set { a = value; } }
        public test()
        {
            a = new ConstraintSet();
        }
        static void Main(string[] args)
        {
            test abc = new test();
            Console.WriteLine("done");
        }
    }
}

I get a stack overflow exception on a's setter in second class and i do not know why. I cannot use the first form because it is not supported by unity engine

+7  A: 

When you write a = value, you are calling the property setter again.

In order to use non-automatic properties, you need to create a separate private backing field, like this:

ConstraintSet a;
public ConstraintSet A { get { return a; } set { a = value; } }
SLaks
Not sure why this answer is downvoted either, given that it's more informative that Cory Larson's...
Jon Skeet
@Jon: I'm surprised I got any votes at all when I posted just seconds behind you :P. I was just too groggy this morning to explain the **why**, so no doubt both SLaks and your answers are better.
Cory Larson
@Cory: I had nothing particularly against your answer, in that it did solve the problem - but without the why. Possibly someone just dislikes people with high rep.
Jon Skeet
+9  A: 

You haven't declared a backing variable - you've just got a property whose getters and setters call themselves. It's not clear to me why the first form isn't supported by Unity - which means it's possible that the equivalent won't be supported either, but it's basically this:

private ConstraintSet aValue;
public ConstraintSet a { get { return aValue; } set { aValue = value; } }

I'd normally have a more conventional name, of course - which means you can get away without the "value` bit:

private ConstraintSet constraints;
public ConstraintSet Constraints
{
    get { return constraints; } 
    set { constraints = value; }
}

To give a bit more detail as to why your current second form is throwing a StackOverflowException, you should always remember that properties are basically methods in disguise. Your broken code looks like this:

public ConstraintSet get_a()
{
    return get_a();
}

public void set_a(ConstraintSet value)
{
    set_a(value);
}

Hopefully it's obvious why that version is blowing the stack. The amended version just sets a variable instead of calling the property again, so it looks like this when expanded:

private ConstraintSet aValue;

public ConstraintSet get_a()
{
    return aValue;
}

public void set_a(ConstraintSet value)
{
    aValue = value;
}
Jon Skeet
@Downvoter: Care to give a reason?
Jon Skeet
simply unity c# compiler does not support what visual c# does. this is because it has to mantain compatibility with mono
Patrik
@Patrik: Mono supports C# 3 as well... C# 3 has been out for nearly 3 years now; this isn't exactly a new feature.
Jon Skeet
i guess this is because of the mac compatibility. i do not know the exact reason but unity compiler says get and set _must_ have a body
Patrik
@Patrik: Mac compatibility should have nothing to do with it. They could easily support it if they bothered - it doesn't require any new framework or runtime features. Basically it sounds like the Unity compiler is just somewhat out of date :(
Jon Skeet
guess so. i hope unity3 will fix this
Patrik
+3  A: 

You need a private backing variable in your public property:

private ConstraintSet _a;
public ConstraintSet a { get { return _a; } set { _a = value; } }
Cory Larson
+2  A: 

You cannot use the same variable name inside the getter and setter.
This will cause it to call itself and will eventually stackoverflow. Too much recursion.
You'll need a backing variable:

private ConstraintSet _a;
public ConstraintSet a { get { return _a; } set { _a = value; } }
Sani Huttunen