Подтвердить что ты не робот

Объем резервной стоимости недвижимости

Возможно ли подобное? Я предполагаю, что нет, но это выглядит хорошо:

class MyClass {
    public int Foo {
        get { return m_foo; }
        set {
            // Bounds checking, or other things that prevent the use
            // of an auto-implemented property
            m_foo = value;
        }

        // Put the backing field actually *in* the scope of the property
        // so that the rest of the class cannot access it.
        private int m_foo;
    }

    void Method() {
        m_foo = 42;    // Can't touch this!
    }
}

Конечно, я знаю, что этот синтаксис неверен, и это не скомпилируется. Это было гипотетически-будущее-С#, чтобы четко изобразить мою идею. Я прошу прощения за несколько гипотетический вопрос, но он слишком специфичен для Programmers.SE.

В компиляторе может быть реализовано что-то вроде этого, которое будет служить одной цели: разрешите только объектам свойств get и set видеть это поле, по существу позволяя этому свойству быть автономным (в качестве автоматически реализованных свойств), позволяя дополнительную логику get/set.

4b9b3361

Ответ 1

Короткий ответ - нет, что невозможно в С# сегодня.

Мы часто получаем такой запрос функции; это приятная особенность в ее более общей форме. Более общая форма состоит в том, чтобы более четко сделать время жизни локальной переменной ортогональной ее области.

Просто чтобы убедиться, что эти условия понятны: переменная - это место хранения, возможно, названное. Каждая переменная имеет продолжительность жизни: количество времени во время выполнения, в котором гарантируется, что переменная относится к допустимому хранилищу. Область имени - это область текста, в которой это имя может использоваться; это концепция времени компиляции, а не концепция времени исполнения. Локальная переменная - это переменная, область видимости которой является блоком оператора.

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

  • Время жизни локального объекта может быть расширено или усечено, если среда выполнения может определить, что это не влияет на действие управляемого кода на текущий поток. Действия других потоков (например, поток финализатора) и неуправляемый код в текущем потоке определяются реализацией.

  • Время жизни локального объекта, которое находится в блоке итератора, асинхронный метод или закрытая внешняя переменная анонимной функции, может быть расширено, чтобы соответствовать или превышать время жизни итератора, задачи, делегировать или дерево выражений, которое его использует.

Очевидно, что не обязательно, чтобы время жизни и область действия локали были связаны друг с другом. Было бы хорошо, если бы мы могли явно иметь локали, которые имеют время жизни экземпляра или статического поля, но область локального. C имеет эту функцию; вы можете создать "статическую" локальную переменную. С# нет. Ваше предложение состоит в том, чтобы разрешить локальную переменную в блоке свойства, которая имеет время жизни экземпляра, но область видимости которого ограничена блоком.

Я бы назвал эту функцию "приятной". У нас есть список потенциальных "хороших" функций буквально до тех пор, пока у вас не будет времени на то, что у вас нет времени, поэтому я не ожидал, что этот человек скоро попадет в верхнюю часть списка. Спасибо за отзывы, хотя; это помогает нам расставить приоритеты в этом списке.

Ответ 2

Здесь я беру на себя следующее:

public class WrappedField<T>
{
    public class Internals
    {
        public T Value;
    }

    private readonly Internals _internals = new Internals();
    private readonly Func<Internals, T> _get;
    private readonly Action<Internals, T> _set;

    public T Value
    {
        get { return _get(_internals); }
        set { _set(_internals, value); }
    }

    public WrappedField(Func<Internals, T> get, Action<Internals, T> set)
    {
        _get = get;
        _set = set;            
    }

    public WrappedField(Func<Internals, T> get, Action<Internals, T> set, T initialValue)
        : this(get, set)
    {
        _set(_internals, initialValue);
    }
}

Использование:

class Program
{
    readonly WrappedField<int> _weight = new WrappedField<int>(
        i => i.Value,           // get
        (i, v) => i.Value = v,  // set
        11);                    // initialValue

    static void Main(string[] args)
    {
        Program p = new Program();
        p._weight.Value = 10;

        Console.WriteLine(p._weight.Value);
    }
}

Ответ 3

В соответствии со спецификациями языка С# 4.0.

Однако, в отличие от полей, свойства не обозначают места хранения. Вместо этого в свойствах есть аксессоры, которые указывают утверждения выполняются, когда их значения читаются или записываются.

Для добавления поля потребуется место в памяти. Нет, это невозможно.

Ответ 4

Если вы хотите избежать генерик, вы всегда можете скрыть проверку _backingField и проверку границ в закрытом внутреннем классе. Вы даже можете скрыть это, сделав внешний класс частичным. Разумеется, между внешним и внутренним классом должно быть какое-то делегирование, которое является обломком. Код для объяснения моих мыслей:

public partial class MyClass
{
    public int Property
    {
        get { return _properties.Property; }
        set { _properties.Property = value; }
    }

    public void Stuff()
    {
        // Can't get to _backingField...
    }
}

public partial class MyClass
{
    private readonly Properties _properties = new Properties();

    private class Properties
    {
        private int _backingField;

        public int Property
        {
            get { return _backingField; }
            set
            {
                // perform checks
                _backingField = value;
            }
        }
    }
}

Но это много кода. Чтобы оправдать всю эту плиту котла, исходная проблема должна быть довольно серьезной...

Ответ 5

Нет, единственное, что может быть внутри тела свойства, это get и set.

Ответ 6

Ну, с ним довольно сложно справиться, возможно, не очень хорошо, а не то, что я действительно использую, но технически это способ замаскировать поле поддержки из остальной части класса.

public class MySuperAwesomeProperty<T>
{
    private T backingField;
    private Func<T, T> getter;
    private Func<T, T> setter;
    public MySuperAwesomeProperty(Func<T, T> getter, Func<T, T> setter)
    {
        this.getter = getter;
        this.setter = setter;
    }

    public T Value
    {
        get
        {
            return getter(backingField);
        }
        set
        {
            backingField = setter(value);
        }
    }
}

public class Foo
{
    public MySuperAwesomeProperty<int> Bar { get; private set; }


    public Foo()
    {
        Bar = new MySuperAwesomeProperty<int>(
            value => value, value => { doStuff(); return value; });

        Bar.Value = 5;

        Console.WriteLine(Bar.Value);
    }

    private void doStuff()
    {
        throw new NotImplementedException();
    }
}