Доступ к полю поддержки в свойстве auto - PullRequest
8 голосов
/ 16 марта 2009

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

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

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

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

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

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

Ответы [ 6 ]

13 голосов
/ 16 марта 2009

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

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

6 голосов
/ 16 марта 2009

Как указано MSDN :

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

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

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

3 голосов
/ 16 марта 2009

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

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

Я бы предложил следующую стратегию. Напишите универсальный класс, который представляет 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); }
    }
}

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

2 голосов
/ 16 марта 2009

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

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 голос
/ 16 марта 2009

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

1 голос
/ 16 марта 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...