Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么类成员是私有的而属性是公共的?_C# - Fatal编程技术网

C# 为什么类成员是私有的而属性是公共的?

C# 为什么类成员是私有的而属性是公共的?,c#,C#,在类中,我们将类成员声明为private,但将属性定义为public 例如: public class student { private int StudentId; private string StudentName; private string Address; } 然后我们用方法赋值 但是如果我们使用get set的属性定义public-like public class student { public int StudentId {get;se

在类中,我们将类成员声明为private,但将属性定义为public

例如:

public class student
{
    private int StudentId;
    private string StudentName;
    private string Address;
} 
然后我们用方法赋值

但是如果我们使用get set的属性定义public-like

public class student
{
    public int StudentId {get;set;};
    public string StudentName{get;set;};
    public string Address{get;set;};
} 

这背后的原因是什么?

类需要控制其公共成员的行为:即控制他们的行为

想象一下,例如,如果
私有字符串StudentName是公开的,因此被外部代码使用(课外
学生
)。然后,您决定要添加验证以限制
StudentName
的长度-如何才能做到这一点?您必须在您的代码(可能还有使用该类的其他人的代码)中找到设置
StudentName
值的所有实例,并在其中添加验证

如果您使用的是
公共字符串Student{get;set;}
,则不会这样做-您可以通过验证轻松将其更改为显式属性:

private string _student;
public string Student
{
    get { return _student; }
    set { if(value.Length <= 20) _student = value;
}
private string\u学生;
公共弦乐学生
{
获取{return\u student;}

set{if(value.Length您是对的-属性通常用作公共属性。 但是:您也可以定义如下属性:

这将使其他类获得您的属性的值,但它们无法更改它


想象一下,如果你要开发一个像程序集一样的项目,其中包含许多复杂的控件。如果你想让用户能够阅读,控件中的值是多少,因为它是经过计算的,你给它一个公共的getter,但给它一个私有的setter,因为你不希望有人操纵内部发生的事情。

这不完全是真的规则是:

尽可能严格地定义所有成员

因此,如果它可以是
私有的
,那么它就是
私有的
。否则如果它必须是
内部的
受保护的
才能工作,那么它就分别是
内部的
受保护的
。否则,如果它必须是
受保护的内部的
才能工作,那么它就是
受保护的内部的
t的
public
,因为它必须是
public
才能工作(程序集之外的某个不从它继承的东西将不得不访问它)

现在,所有这些都表明,通常情况下,我们会有大部分的
私有
字段和大部分的
公共
属性

让我们考虑一下,如果我们有一个<代码>公共<代码>字段。它是有效的,可以工作,甚至在非常有限的情况下也是有用的。但是它也更脆弱。如果它<代码>公共< /代码>,让任何其他代码将它设置为任何值,无论多么愚蠢。没关系,因为当我们制定一个字段<代码>公共< /代码>时,我们在说。“没有愚蠢的价值观”*

但是,如果我们突然意识到存在一些愚蠢的值,或者每次字段被更改时我们都需要做一些事情,或者我们需要使用一些仅属性的数据绑定。在这里,我们必须将字段转换为属性,这是一个突破性的更改;任何使用该类的代码都必须重新编译,这不是一个大问题如果我们是唯一使用该类的人,但如果该类位于其他人正在使用的库中,则进行交易

但是,如果它是一个属性,那么我们只需将一个自动属性
{get;set;}
转换为一个具有自定义实现的属性
{get{/*do stuff并返回值*/}set{/*do stuff*/}
。从类外部看,它似乎没有发生任何变化,我们也没有破坏任何东西

因此,99.99%的情况下,如果你打算将一个字段
公开
,你最好在那里使用一个属性,以防万一

另一方面,如果我们有一个没有逻辑的
private
属性,那么getter和setter方法不会给我们带来任何好处。不会有任何成本,但它们是毫无意义的。所以我们只使用一个字段。如果我们将来不得不使用私有属性,那也没关系,因为唯一需要重新编译的代码是d就是这个问题中的类,我们正在重新编译它

因此,我们以几乎所有字段都是
private
而几乎所有没有任何自定义逻辑的属性都是
受保护的
public
的情况结束


*或者它是一个
private
internal
类,我们从外部承诺不会将其设置为愚蠢的东西,但最好是强制执行承诺,而不是在可能的情况下做出承诺。

不直接设置字段,而是通过属性遵循面向对象的封装原则。这包括类是bos类应该始终控制对其数据的访问(无论是读还是写)。有时这意味着它们需要执行额外的步骤来确保数据一致性。但即使它们不这样做,调用方也应该隐藏不这样做的事实,因为这与它们无关(关注点分离)。因此,一条简单的规则是:对象数据没有捷径。如果你想获取其中的一部分,你必须要求类将其提供给你。在C#中,这就是属性的用途。

使用属性并将其公开背后有多种原因

  • 将类字段标记为public&公开是一种风险,正如您将看到的那样 无法控制分配和返回的内容

  • 要在值更改时进入调试器吗?只需在setter中添加一个断点

  • 要记录所有访问吗?只需将日志添加到getter。 属性用于数据绑定;字段不用于数据绑定

  • 在私有成员上添加验证(如值不能设置为负值)

  • 如果为null、空或零,则返回一些默认值

  • 属性可以声明为读/写、只读或只读

  • 其他好处,反射和数据绑定

  • 我在那里
    public int StudentId {get; private set;}
    
    public interface IStudent
    {
        int StudentId { get; set; }
        string StudentName { get; set; }
        string Address { get; set; }
    }
    
    public class Student : IStudent
    {
        public int StudentId { get; set; }
        public string StudentName { get; set; }
        public string Address { get; set; }
    }