【问题标题】:Getters and Setters - How does "value" work, particularly in an if statement?Getter 和 Setter - “值”如何工作,尤其是在 if 语句中?
【发布时间】:2019-01-08 03:08:17
【问题描述】:

我一直在看这个视频:https://www.youtube.com/watch?v=GhQdlIFylQ8&t=11038s

我正在 3:54:60 完成“Getters & Setters”(C# 的其他主题在任何需要的上下文的描述中)。

这是我创建的一个类,用于打印到控制台以及“Getter and Setter”。

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;
            }
        }
    }
}

这是打印出两个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();
    }
}

但是,我尝试通过查看如何打印除歌曲标题以外的其他内容来尝试“Getters and Setters”。

当我运行程序时,它会在不同的行上打印出 HelloKashmir

如何让它打印 ERROR 或除歌曲标题以外的其他内容(或者我可以通过哪些其他方式来打印)?

【问题讨论】:

  • 当你给一个属性赋值时,比如Title = "Ice cream";,那么这个属性的setter就会被调用。属性设置器中的特殊value 变量包含分配给属性的值(在我的示例中为"Ice cream")。您的程序没有打印出“错误”与那个特殊的value 变量的性质无关。而是非常仔细地查看您的 if 语句在属性设置器中的作用,同时考虑到属性获取器实际在做什么。还要注意 setter 何时被调用,何时不被调用......
  • 你有一个简单的逻辑错误。在学习的早期学习使用调试器。
  • 逻辑错误是,在类构造函数中,您正在设置支持字段。值检查由属性设置器完成。设置支持字段不会触发 setter 中的验证。将在构造函数中传递的值直接分配给属性,以便评估条件。不要尝试更改 value 内容,而是使用验证值设置字段。你也可以在这里放弃支持使用自动属性。

标签: c# oop getter-setter


【解决方案1】:

这里发生了一件有趣的事情,即使是经验丰富的开发人员也偶尔会绊倒……它忽略了支持字段和属性之间的区别。这种情况时有发生......并且绝对让开发人员感到困惑,直到他们意识到他们已经犯了一个 Visual Studio 智能感知辅助错误。如果您将支持字段命名为与属性名称相同,则可能性会加倍...仅在大小写时有所不同。

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 属性可能会给您留下一些可能是错误的信息。

【讨论】:

  • 为了确保我得到正确的想法,我将谈谈我认为我的问题是什么,如果我有任何错误,如果你或任何人允许我,我将不胜感激知道。我的问题之一是我已经设置了属性Title 所需的支持字段,但实际上我并没有set 属性本身以便将其打印到控制台。我的下一个问题是我以不必要的方式使用了value,从您的回答中得知更改传入的value 是我通常不想做的事情。
  • Right - 设置 Title 运行您的 Title setter...依次设置标题支持字段。是的……设置value 几乎是不合适的。通常,您只需将其放入您的支持领域。请注意,有时您可能会将当前的支持字段与value 进行比较以决定要做什么......但听起来您已经到了那里!
【解决方案2】:

您不应将“错误”分配给 Value 关键字。

Value 关键字是保存输入。如果您想在为字段分配值之前执行验证,这很有用。如果您将某些内容分配给 Value,则该类将不会保留它。

编辑 - 正如下面评论中提到的 - 您的代码没有使用属性设置器,但它是通过构造函数设置值

你有两个选择 -

选项 1 - 在构造函数中添加相同的验证。
选项 2 - 在构造函数中设置属性而不是字段

选项 2 对我来说更有意义,因为它避免了代码重复。

您将不得不对标题属性进行小幅更改

    public string Title
    {
        get { return title; }

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

            } else
            {
                title = value;
            }
        }
    }

【讨论】:

  • OP 声称它可以编译并运行。老实说,我从来没有尝试分配给它。
  • 虽然到目前为止你的解释是正确的,但它并没有完全解决问题。请注意,问题中的代码实际上没有属性分配,因此永远不会调用 setter...
猜你喜欢
  • 1970-01-01
  • 2011-01-03
  • 2022-11-05
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 2022-07-21
相关资源
最近更新 更多