在C#中的Get和Set

5

我对C#语法还不熟悉。我编写了以下类(我的网站主页的代码后台):

public partial class MasterPagePro : System.Web.UI.MasterPage
{
    public String pageTitle
    {
        get
        {
            if (this.pageTitle == null)
                return "";
            else
                return " - " + this.pageTitle;
        }
    }

}

然而,当我尝试在HTML中像这样访问pageTitle时:
<title>MySite<%=pageTitle%></title>

我遇到了一个stackoverflow错误。看代码,很明显这个问题是方法在递归调用自己,但是我不知道该怎么写来解决这个问题。我可以像下面这样做:

public partial class MasterPagePro : System.Web.UI.MasterPage
{
    private String _pageTitle

    public String pageTitle
    {
        get
        {
            if (_pageTitle == null)
                return "";
            else
                return " - " + _pageTitle;
        }
        set { _pageTitle = value; }
    }
}

但这似乎违背了使用语法快捷方式的初衷。那么正确的做法是什么呢?

6个回答

7
在你的第一个例子中,你期望编译器知道你是否真的想要递归调用同一个属性。由于编译器无法知道你的意图,它将按照代码编写,正如你指出的那样,会导致堆栈溢出。
语法缩写是为了当你有一个简单的属性和一个赋值/返回的setter/getter时使用的。编译器为你创建后备类成员,并生成get/set例程。
例如:
class foo {

 public int myInt;

 public int MyInt { get { return myInt;} 
                    set { myInt = value;} }

 }

vs

 class foo {

 public int MyInt { get; set; }

 }

在这种情况下,您要做什么是完全明确的,因此编译器可以帮助自动生成必需的内容。

如果您需要实现自定义 Setter/Getter 功能,并设置一个值,您必须使用支持类成员,就像您在第二个示例中展示的那样。


6
当您以这种方式使用getter时,您还需要手动添加像第二个示例中那样的字段。
您不能像第一个示例中那样引用相同的属性。
您提到了一种语法快捷方式,但据我所知,您并没有使用快捷方式。
当在返回变量之前未对其进行任何处理时,属性的快捷方式将是:
public string pageTitle{get;set;}

这会自动为您创建支持字段。


3
你提供的第二个代码块是我所知道的实现包含逻辑的复杂属性的“正确”方式。

1
“语法快捷方式”并不一定是为了成为语法快捷方式。如果您想使用自动属性,可以使用 public String PageTitle { get; set; }
所有内容都在那里为您提供,包括后备字段。属性的真正目的是将后备字段从实现者隐藏起来...面向对象编程、抽象和继承以及所有的那些东西。使用属性,您可以添加验证或更改返回方式的格式,而无需查找对后备字段的每个访问实例。

1

另外,属性(get 和 set 语法)通常使用 PascalCase,即 PageTitle。


谢谢。我来自Java背景,它使用不同的约定。我的命名方案目前相当混乱。 - Oliver
可以理解。我也是从Java转过来的。C#的约定有时可能非常奇怪。上周我实际上写了这样的代码:Fixation.Fixation Fixation = new Fixation()。也许不是最好的命名选择,但从类外部来看更有意义,所以我坚持使用它。 - Johan Tidén

1
  • 列表项

您正在返回属性,这将再次进入get。 这个属性有后备字段吗?

您提出的方法是正确的。 属性的想法只是在get和set方法上的语法糖,并不是为了消除对本地字段的需求。 自动属性是语法糖,但在这种情况下,您无法提供实现。

您可能正在考虑自动属性:

public string MyName { get; set; }

但是对于这些,您无法实现get或set。

此外,如果您为属性提供了非平凡的实现,请注意以下几个指南:

  • get和set操作应该轻量级,即快速。
  • 属性的返回值在调用之间不应更改,除非将其设置为不同的值(即,如果类的状态在内部导致不同的值,则建议使用方法而不是返回值来返回该值)。

哦,我明白了。我原以为这样做会隐式地在某个地方创建一个后备字段。 - Oliver
@Oliver 在自动属性的情况下,后备字段只会隐式创建。 - Adam Houldsworth
您不一定希望它在后台自动生成一个字段。例如,当从接口继承时:bool SupportsSomeProperty { get { return true; } } - Mike Park

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接