Различие между участником переменное и свойство элемента?

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

public class Car
{

    int speed; //Is this sufficient enough if Car will only set and get it.

    public Car(int initialSpeed)
    {
        speed = initialSpeed;
    }

    //Is this actually necessary, is it only for setting and getting the member
        //variable or does it add some benefit to it, such as caching and if so,
        //how does caching work with properties.
    public int Speed 
    {
        get{return speed;}
        set{speed = value;}
    }

        //Which is better?
        public void MultiplySpeed(int multiply)
        {
            speed = speed * multiply; //Line 1
            this.Speed = this.Speed * multiply; //Line 2

            //Change speed value many times
            speed = speed + speed + speed;
            speed = speed * speed;
            speed = speed / 3;
            speed = speed - 4;

        }
}

В вышеупомянутом, если у меня нет свойства Speed, чтобы установить и получить переменную скорость, и я решаю изменить международную скорость на интервал spd, я должен буду изменить скорость на spd везде, это используется, однако, если я использую свойство, такое как Скорость, чтобы установить и получить скорость, я должен буду просто изменить скорость на spd в получении и наборе свойства, таким образом, в моем методе MutilplySpeed, материале как вышеупомянутое это. Скорость = это. Скорость + это. Скорость + это. Скорость не повредится.

16
задан Xaisoft 17 February 2010 в 18:11
поделиться

7 ответов

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

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

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

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

  • Читабельность против скорости
  • "Атомарность"
  • Другие побочные эффекты

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

Атомарность может быть проблемой. В примере вашего кода у нас есть поле speed, которое открыто через свойство Speed. Если метод MultiplySpeed должен выполнить несколько обновлений значения, эти промежуточные значения будут доступны через свойство Speed в разное время, пока идет вычисление. Это верно независимо от того, обновляете ли вы поле напрямую или через свойство. В подобных случаях, возможно, лучше сначала поместить значение в локальную переменную, использовать ее для вычислений и по завершении присвоить значение переменной обратно свойству.

Наконец, другие побочные эффекты. Может оказаться, что изменение значения Speed должно вызвать событие (например, SpeedChanged). В подобных случаях, вероятно, также будет хорошей идеей не выполнять обновление, пока не будет выполнен расчет.

Мне нравится думать о свойстве как о контракте, а о поле как о реализации. Любой (кроме ядра моего типа), кому нужно значение, должен использовать контракт. Опираться на реализацию следует только в том случае, если есть веские причины обойти контракт.

И да, если вы инкапсулируете доступ к полю в свойстве, то, естественно, изменение имени поля потребует меньше обновлений (и, возможно, имя поля станет менее важным).

Надеюсь, это имеет смысл и не слишком отклоняется от темы ;)

23
ответ дан 30 November 2019 в 16:58
поделиться

он не добавляет кэширования, но обеспечивает согласованный интерфейс.

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

Также внутри класса вы должны снова получить доступ к свойству для согласованности (представьте вышеупомянутый сценарий, где у вас был класс, который напрямую обращался к переменной-члену).

1
ответ дан 30 November 2019 в 16:58
поделиться
class EmptyProcessor : IProcessor {

    [Obsolete("EmptyProcessor.OnProcess should not be directly accessed", true)]
    public event EventHandler OnProcess { 
        add { throw new NotImplementedException(" :( "); }
        remove { }
    }
}

В этой ситуации параметр true в Oursolete вызывает исключение времени компиляции. Итак:

EmptyProcessor processor1 = new EmptyProcessor();
IProcessor processor2 = new EmptyProcessor();

processor1.OnProcess += handler;  // <-- compile-time error
processor2.OnProcess += handler;  // <-- run-time error
-121--3690404-

Одну вещь вы забыли упомянуть, свойства помогут вам, когда вы расширяете свой класс. Если класс правильно разработан, переменные в базовом классе должны быть частными . Без фактических свойств public , то есть. У вас не будет пути на доступ к этим частным переменным из расширенного класса. Мы говорим о публичных против частных, и я не имею права на защиту по причине:).

Просто некоторые примечания стоит упомянуть:

  • свойства помогают, когда класс расширен
  • свойства для меня сделать код немного более читаемым (в дополнение this.privateVariable verson PublicPropertyVariiveName)
  • свойства могут обеспечить только для чтения, частных аппаратов, общедоступных получает и т.д. (гораздо более читаемые для других программистов). Рассмотрим случай, когда IDentifier нуждается в публичном получении, но частный набор
  • Лично мне слишком много получает/множеств кажется усложняет код, делает код менее читаемым, слишком много лишнего ненужного синтаксиса
  • наследование/расширение до расширенного класса не позволяет наследовать частные переменные, свойства являются ответом. (опять же нет упоминания о защищенных здесь, это другая история)
  • Для меня, даже если класс имеет частную переменную, мои методы класса по-прежнему используют свойство для доступа или использования этой частной переменной
  • Не забывайте о проверке, это значительно облегчает проверку особенно читаемости.

Это просто некоторые общие вещи (мои 2 цента, хотя на большинство из них).

-121--1728851-

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

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

1
ответ дан 30 November 2019 в 16:58
поделиться

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

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

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

-121--1665230-

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

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

-121--2451620-

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

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

1
ответ дан 30 November 2019 в 16:58
поделиться

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

Здесь я заменил свойство Speed в вашем примере на автоматическое свойство. Обратите внимание, что переменная-член исчезла, и ваш класс должен обращаться к ней через свойство.

public class Car
{
    public Car(int initialSpeed)
    {
        Speed = initialSpeed;
    }

    public int Speed { get; set; }

    public void MultiplySpeed(int multiply)
    {
        Speed *= multiply;
    }
}

Вы также можете использовать другой способ, называемый "get с private set". Это означает, что getter является публичным, а setter - приватным. Вы определяете его следующим образом:

    public int Speed { get; private set; }

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

8
ответ дан 30 November 2019 в 16:58
поделиться

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

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

1
ответ дан 30 November 2019 в 16:58
поделиться

На самом деле вы можете сделать также

n = (n - 1) + ((!(n - 1)) * max);
-121--4268335-

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

enum SearchType { Forward, Reverse }

Если перечисление является общим и может использоваться несколькими классами для различных сценариев, то я был бы склонен использовать положить его в свой собственный файл. Например, приведенное ниже можно использовать для нескольких целей:

enum Result { Success, Error }
-121--651628-

Одну вещь, которую вы забыли упомянуть, свойства помогут вам при расширении вашего класса. Если класс правильно разработан, переменные в базовом классе должны быть частными . Без фактических свойств public , то есть. Доступ к этим частным переменным из расширенного класса невозможен. Мы говорим о публичных против частных, и я не имею права на защиту по причине:).

Просто некоторые примечания стоит упомянуть:

  • свойства помогают, когда класс расширен
  • свойства для меня сделать код немного более читаемым (в дополнение this.privateVariable verson PublicPropertyVariiveName)
  • свойства могут обеспечить только для чтения, частных аппаратов, общедоступных получает и т.д. (гораздо более читаемые для других программистов). Рассмотрим случай, когда IDentifier нуждается в публичном получении, но частный набор
  • Лично мне слишком много получает/множеств кажется усложняет код, делает код менее читаемым, слишком много лишнего ненужного синтаксиса
  • наследование/расширение до расширенного класса не позволяет наследовать частные переменные, свойства являются ответом. (опять же нет упоминания о защищенных здесь, это другая история)
  • Для меня, даже если класс имеет частную переменную, мои методы класса по-прежнему используют свойство для доступа или использования этой частной переменной
  • Не забывайте о проверке, это значительно облегчает проверку особенно читаемости.

Это просто некоторые общие вещи (мои 2 цента, хотя на большинство из них).

0
ответ дан 30 November 2019 в 16:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: