为什么在属性访问器中应该使用私有变量?

27

对不起,如果我很菜鸟,请原谅。我有一个疑问,为什么我们要使用私有变量并使用属性来设置它们?

为什么不能只使用属性?

我说的是像这样的情况

private string _testVariable;

public string MyProperty
{
    get { return _testVariable;}
    set {_testVariable = value;}
}

我在考虑只使用

public string MyProperty { get; set; } 

为什么要冗余的私有变量?这两种策略有区别吗?请有经验的人士解惑一下。

谢谢。


抱歉,我只是从我的第一个片段复制过来..忘了在第二个片段中删除..谢谢 :) - Mahesh Velaga
问一些初级问题也没关系。 - Cheeso
谢谢,我是软件开发新手,但我想学习 :) - Mahesh Velaga
9个回答

32

你的例子在语义上是相同的。简洁的属性声明语法(只使用 { get; set; })是C# 3.0中提供的一种快捷方式。实际上,编译器会像在第一个示例中一样创建一个私有的备份变量和一个简单的 getter 和 setter。

如果你只是创建一个 getter 和 setter(当两者都没有实际发生任何事情时),那么简明的语法是一个不错的选择。如果你需要在设置值时执行任何其他操作(例如重绘控件),则需要使用完整的语法。


如果你不确定是否需要使用额外的逻辑,一个好处是,如果你使用简写,你总是可以稍后增加它,而外部代码不会注意到它曾经只是一个被吹嘘的变量。 - Camilo Martin

16

为什么需要冗余的私有变量?这两种策略有区别吗?能否请有经验的人给予一定的指导。

如果你只是读取/写入一个变量,那么不需要。否则,有两个原因需要使用私有变量:

数据验证

// Data validation
public class IntWrapper
{
    private int _value;
    public int Value
    {
        get { return _value; }
        set
        {
            if (value < 0) { throw new Exception("Value must be >= 0"); }
            _value = value;
        }
    }
}

Getter/setter将底层数据存储封装起来

public class StringBuffer
{
    List<char> chars = new List<char>();

    // Wraps up an underlying data store
    public string Value
    {
        get { return new String(chars.ToArray()); }
        set { chars = new List<char>(value.ToCharArray()); }
    }

    public void Write(string s) { Write(chars.Count, s); }

    public void Write(int index, string s)
    {
        if (index > chars.Count) { throw new Exception("Out of Range"); }
        foreach(char c in s)
        {
            if (index < chars.Count) { chars[index] = c; }
            else { chars.Add(c); }
            index++;
        }
    }
}

2
你提供的第二个例子是:
public string MyProperty { get; set; }

这个功能只在较新版本的.Net框架中可用(我相信是从v3.0开始)。

第一个示例允许您在return和赋值语句上设置断点,当属性被赋值/读取时,会使调试器停止。


1
不,您可以将 .Net 2.0 用作目标。但是您需要一个 C# 3 编译器。 - helium

2

Mashesh, 我们都是从某个地方开始的!你问了这个问题:关于私有变量和属性的区别:

private string _testVariable;

public string MyProperty
{
    get { return _testVariable;}
    set {_testVariable = value;}
}

-or-

public string MyProperty { get; set; }

你是否考虑过:

public string MyProperty { get; private set; }

你可以将范围应用于属性的getter和setter...很酷的东西。哦,是的...当在定义类中使用这种类型的属性(比如在构造函数中)时,请在前面加上'this.' - 这样赋值看起来像 'this.MyProperty = "An Assigned String";'。这使你的意图更加明确...

2
第一段代码片段允许您修改某些私有类状态。将私有状态包装在属性中很好,因为它隐藏了实现细节。稍后,您可以更改实现方式,而属性(外部接口)可能保持不变。
例如,假设您不是在setter中设置单个字符串,而是在某种私有存储中设置字符串。您可以将其写入文件或写入共享内存。或者,您只计算字符串的哈希值,而不存储它,就像处理密码时所做的那样。
第二段代码片段中的自动属性与私有变量无关。自动属性设计与第一个片段中使用的显式属性设计一样,允许未来进行修改。作为修改的一部分,例如,您可以从自动属性转换为显式实现的属性。

0

属性基本上是字段的包装器。这个包装器使得变量可以从外部世界使用。在C#3.0中,您可以简单地声明一个属性,如public string MyProperty { get; set; }编译器会自动声明一个私有变量,并为其提供get和set方法。如果您需要在声明属性的类内执行任何计算,则应使用私有字段。


0
有时候当你第一次编写代码的时候,并不知道之后是否需要添加使用私有变量的代码。当然,如果需要的话可以在稍后添加。我通常会自动创建私有变量,因为我认为它将在后面被使用。
这可能更相关于大型企业应用程序或快速发展的应用程序(敏捷开发),因为在初始编码期间可能并不知道完整实现的情况。

1
将自动属性更改为由显式私有变量支持的属性相当容易且不会破坏代码。我不明白为什么你想在可能有人需要它的情况下毫无必要地使代码混乱。你也会在代码的其他部分这样做吗? - Chris
不,只是属性。始终创建私有变量可以使我的代码状态可预测。如果您使用代码生成器创建所有属性,则更容易做到这一点 :) 但是您的观点很好。 - DOK

0

我讨厌在不需要的情况下使用备份变量,因为它会导致比必要的更复杂。

显然,如果您需要在getter或setter中执行某些特殊操作,则应该使用完整的语义形式而不是简写。

此外,我喜欢将属性用作调试属性设置或使用方式的方法,有时这并不那么明显,因为反射的缘故,这也是我喜欢使用它们的原因之一。

当存在可能通过属性本身或备份变量在类内部访问备份变量时,我发现尝试调试代码非常令人沮丧,而没有任何提示告诉编码者正确的访问方式。

您可以在类内部访问备份变量以及属性,那么哪种方式才是正确的? 这并不明显...


-1

这与C#语言本身不太相关,更多的是应用程序相关。

使用属性的一个原因是,在许多框架中,它被视为“特殊”的。例如,Silverlight和WPF将绑定到属性而不是字段。


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