Вопрос

Есть ли способ получить доступ к вспомогательному полю для свойства для проверки, отслеживания изменений и т. д.?

Возможно ли что-то вроде следующего? Если нет, то есть ли планы сделать это в .NET 4 / C # 4?

public string Name
{
    get;
    set
    {
        if (value != <Keyword>)
        {
            RaiseEvent();
        }
        <Keyword> = value;
    }
}

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

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

Изменить: я изменился < Защитное поле & Gt; к & л; Ключевое слово & Gt ;. Я бы предложил новое ключевое слово, похожее на значение. field подойдет, хотя я уверен, что он используется во многих существующих кодах.

Это было полезно?

Решение

Прочитав ваши комментарии в ответе Мехрдада, я думаю, что немного лучше понимаю вашу проблему.

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

Я бы предложил следующую стратегию. Напишите универсальный класс, который представляет ValidatedValue. Этот класс содержит только значение поддержки и разрешает доступ / мутацию только через методы get и set. Делегат передается в ValidatedValue для представления логики проверки:

public class ValidatedValue< T >
{
    private T m_val;
    public ValidationFn m_validationFn;

    public delegate bool ValidationFn( T fn );

    public ValidatedValue( ValidationFn validationFn )
    {
        m_validationFn = validationFn;
    }

    public T get()
    {
        return m_val;
    }

    public void set(T v)
    {
        if (m_validationFn(v))
        {
            m_val = v;
        }
    }
}

Конечно, вы можете добавить больше делегатов по мере необходимости (например, для поддержки уведомления до / после изменения).

Теперь ваш класс будет использовать ValidatedValue вместо резервного хранилища для вашей собственности.

В приведенном ниже примере показан класс MyClass с целым числом, значение которого не превышает 100. Обратите внимание, что логика для выброса исключения находится в MyClass, а не в ValidatedValue. Это позволяет вам выполнять сложные правила проверки, которые зависят от другого состояния, содержащегося в MyClass. Лямбда-нотация использовалась для создания делегата валидации - вместо этого вы могли бы привязаться к функции-члену.

public partial class MyClass
{
    private ValidatedValue<int> m_foo;

    public MyClass()
    {
        m_foo = new ValidatedValue<int>(
            v => 
            {
                if (v >= 100) RaiseError();
                return true;
            }
        );
    }

    private void RaiseError()
    {
        // Put your logic here....
        throw new NotImplementedException();
    }

    public int Foo
    {
        get { return m_foo.get(); }
        set { m_foo.set(value); }
    }
}

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

Другие советы

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

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

Как MSDN заявляет:

  

& "В C # 3.0 и более поздних версиях реализовано автоматически   свойства делают объявление свойства   более лаконично, когда нет дополнительной логики   требуется в свойствах доступа.   Они также позволяют клиентскому коду создавать   объекты Когда вы объявляете свойство как   показано в следующем примере,   компилятор создает приват, аноним   поле доступа может быть доступно только   через собственность получить и установить   аксессоров Quot. &;

Поскольку у вас есть дополнительная логика в средствах доступа, использование автоматически реализуемых свойств не подходит для вашего сценария.

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

Нет, но вы можете в подклассе:

public class Base
{
    public string Name
    {
        get;
        virtual set;
    }
}

public class Subclass : Base
{
    // FIXME Unsure as to the exact syntax.
    public string Name
    {
        override set
        {
            if (value != base.Name)
            {
                RaiseEvent();
            }

            base.Name = value;
        }
    }
}

Если вы собираетесь это сделать, почему вы используете свойства авто?!

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

Боюсь, ты не можешь этого сделать. Это одна из причин, по которой я начал писать MoXAML Power Toys , чтобы преобразовать автоматические свойства в свойства уведомлений.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top