Исключение переполнения стека в установщике c # - PullRequest
13 голосов
/ 18 июля 2010

Это просто объяснить: это работает

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");
        }
    }
}

это не

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");
        }
    }
}

Я получаю исключение переполнения стека для установщика a во втором классе, и я не знаю почему,Я не могу использовать первую форму, потому что она не поддерживается механизмом единства

Ответы [ 4 ]

35 голосов
/ 18 июля 2010

Когда вы пишете a = value, вы снова вызываете установщик свойств.

Чтобы использовать неавтоматические свойства, вам нужно создать отдельное приватное поле поддержки, например:

ConstraintSet a;
public ConstraintSet A { get { return a; } set { a = value; } }
17 голосов
/ 18 июля 2010

Вы не объявили резервную переменную - вы только что получили свойство, чьи методы получения и установки называют себя. Мне не понятно , почему первая форма не поддерживается Unity - это означает, что возможно, что эквивалент также не будет поддерживаться, но в основном это так:

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

Конечно, у меня обычно было бы более условное имя, что означает, что вы можете обойтись без бита "value`:

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

Чтобы немного подробнее объяснить, почему ваша текущая вторая форма выдает StackOverflowException, вы всегда должны помнить, что свойства в основном являются скрытыми методами. Ваш неработающий код выглядит так:

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

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

Надеюсь, очевидно, почему эта версия взорвала стек. Измененная версия просто устанавливает переменную вместо того, чтобы снова вызывать свойство, поэтому при раскрытии она выглядит следующим образом:

private ConstraintSet aValue;

public ConstraintSet get_a()
{
    return aValue;
}

public void set_a(ConstraintSet value)
{
    aValue = value;
}
4 голосов
/ 18 июля 2010

Вы не можете использовать одно и то же имя переменной внутри метода получения и установки.
Это заставит его вызывать себя и в конечном итоге приведет к переполнению стека.Слишком много рекурсии.
Вам понадобится вспомогательная переменная:

private ConstraintSet _a;
public ConstraintSet a { get { return _a; } set { _a = value; } }
3 голосов
/ 18 июля 2010

Вам нужна личная переменная в вашем публичном свойстве:

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