Получатели и установщики - как работает «значение», особенно в операторе if? - PullRequest
0 голосов
/ 05 января 2019

Я работал над этим видео: https://www.youtube.com/watch?v=GhQdlIFylQ8&t=11038s

Я работаю через "Getters & Setters" в 3:54:60 (другие темы для C # находятся в описании для любого необходимого контекста).

Это класс, который я создал для печати на Консоль, а также для «Получателя и Установщика».

class Song
{
    private string title;
    public string artist;
    public int duration;

    public Song(string aTitle, string aArtist, int aDuration)
    {
        title = aTitle;
        artist = aArtist;
        duration = aDuration;
    }

    public string Title
    {
        get { return title; }
        set {
            if (value == "Hello")
            {
                value = "ERROR";

            } else
            {
                title = value;
            }
        }
    }
}

И это код "Main" для вывода заголовков двух Song объектов: "hello" и "kashmir".

class Program
{
    static void Main(string[] args)
    {
        Song hello = new Song("Hello", "Adele", 400);
        Song kashmir = new Song("Kashmir", "Green Day", 200);

        Console.WriteLine(hello.Title);
        Console.WriteLine(kashmir.Title);
        Console.ReadLine();
    }
}

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

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

Как мне заставить его напечатать ERROR или что-то еще, кроме названий песен (или каким другим способом я могу это сделать)?

Ответы [ 2 ]

0 голосов
/ 05 января 2019

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

class Song
{
    private string title;  //--> this is the "backing field" for the property "Title"
    public string artist;
    public int duration;

    public Song(string aTitle, string aArtist, int aDuration)
    {
        //title = aTitle; //--> this only sets the backing field...not the "Title" property
        Title = aTitle;  //--> this sets your "Title" property
        artist = aArtist;
        duration = aDuration;
    }

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

    public string Title
    {
        get { return title; }

        set {
            if (value == "Hello")
            {
                //value = "ERROR"; //--> this only changes the incoming value
                title = "ERROR";   //--> this sets your backing field

            } else
            {
                title = value;
            }
        }
    }
}

Сказав все это, нередко можно увидеть, как конструктор устанавливает только резервные поля, а не проходит через иногда дорогой проверочный код свойства set. Часто это свойство public API для пользователей вашего типа для установки значения ... в то время как конструктор остается внутренним или закрытым и используется только для заполнения значений, которые были сохранены где-то .. как в базе данных. Хорошая идея? Может быть, а может и нет. Как вы только что обнаружили, обход свойства set может привести к ошибкам.

0 голосов
/ 05 января 2019

Не следует назначать «Ошибка» ключевому слову Value.

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

РЕДАКТИРОВАТЬ - Как упомянуто в комментариях ниже - ваш код не использует установщик свойств , но он устанавливает значения через конструктор .

У вас есть два варианта -

Вариант 1 - Добавить те же проверки в конструкторе.
Вариант 2. В конструкторе задайте свойства вместо полей

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

Вам придется внести небольшое изменение в заголовок proprty

    public string Title
    {
        get { return title; }

        set {
            if (value == "Hello")
            {
                title = "ERROR";

            } else
            {
                title = value;
            }
        }
    }
...