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

Разница между переменной-членом и элементом-членом?

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

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 ​​для установки и получения переменной скорости, и я решаю изменить скорость int на int spd, мне придется менять скорость на spd везде, где она используется, если я использую свойство, такое как Speed ​​для установки и получения скорости, мне просто нужно будет изменить скорость на spd в get и set свойства, так что в моем методе MutilplySpeed, как и выше. Скорость = this.Speed ​​+ this.Speed ​​+ this.Speed ​​не сломается.

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

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

Я надеюсь, что это имеет смысл, и не слишком много от темы;)

Ответ 2

Я согласен с ответом Фредерика. Одна вещь, которая делает его немного меньше работы, чтобы следовать его совету, - использовать автоматические свойства. Это просто свойства, которые автоматически генерируют стандартную логику 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 with private set". Это означает, что геттер является общедоступным, но сеттер является закрытым. Вы определяете его следующим образом:

    public int Speed { get; private set; }

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

Только некоторые заметки, которые стоит упомянуть:

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

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

Ответ 8

По-моему, дизайн языка нарушен. Не должно быть двух способов делать вещи с таким большим количеством семантического перекрытия. Свойства/Поля должны были легко обеспечить преимущества любого подхода в зависимости от того, как они используются. Если программа делает минимальное использование свойств Property, они должны действовать так же, как поля. Кроме того, не должно быть необходимости объявлять пустой get; и установить; методов в этом случае. Различия кажутся мне искусственными.

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