8

示例代码(替代代码如下),

// person.cs
using System;
class Person
{
    private string myName ="N/A";

    // Declare a Name property of type string:
    public string Name
    {
        get 
        {
           return myName; 
        }
        set 
        {
           myName = value; 
        }
    }
    public override string ToString()
    {
        return "Name = " + Name;
    }

    public static void Main()
    {
        Person person = new Person();
        Console.WriteLine("Person details - {0}", person);
        person.Name = "Joe";
        Console.WriteLine("Person details - {0}", person);

    }
}

不能直接写,把myNameprivate改成public,不需要再声明一个public变量Name,也不需要get和set?

替代代码

    // person.cs
    using System;
    class Person
    {

        public string myName ="N/A";

        public override string ToString()
        {
            return "Name = " + myName;
        }

        public static void Main()
        {
            Person person = new Person();
            Console.WriteLine("Person details - {0}", person);
            person.myName = "Joe";
            Console.WriteLine("Person details - {0}", person);

        }
    }
4

6 回答 6

17

外部可见的属性比字段更好,因为:

  • 属性允许更好的封装。字段是一个固定的实现,允许消费者直接访问。特性:

    • 松散耦合(因为基础字段可以随时从变量更改为数据库)

    • 允许自定义逻辑(验证、事件通知、延迟加载等)

    • 控制访问(因为逻辑可以内置在 get/set 中,甚至可以声明为只读或只写)。

  • 字段不能在接口中使用。这是测试驱动开发(接口优先)的障碍。

  • 自动或自动实现的属性与字段一样易于声明,并且经过优化以与字段同等执行。见这里

  • 声明一个外部可见的字段(public、protected、protected internal)是违反 FxCop的。参见规则 CA1051

  • 将字段更改为属性是一项重大更改,因为需要重新编译调用代码(也适用于二进制序列化)。

  • .NET 中的许多库都可以识别属性,用于诸如 XML 序列化、WPF 绑定、ASP.NET 2 路绑定等任务,并且还可以被 Visual Studio 设计器识别。

于 2013-06-19T08:37:27.347 回答
10

您正在破解 OOP 的基础之一 -> 信息隐藏/封装

通过将您的属性定义为公共属性,您可以让每个人都可以访问它们,并且可以根据需要更改(损坏)它们。这样你就不能保证你的对象会一直处于一致的状态。

来自维基百科

在编程语言中,封装用于指代两个相关但不同的概念之一,有时指的是它们的组合[1][2]:
- 一种用于限制对某些对象组件的访问的语言机制。[3][4 ]
- 一种语言结构,有助于将数据与操作该数据的方法(或其他功能)捆绑在一起。[5][6]

一些编程语言研究人员和学者单独使用第一个含义或将其与第二个含义结合使用作为面向对象编程的显着特征,而其他提供词法闭包的编程语言将封装视为与面向对象正交的语言的一个特征。

第二个定义的动机是,在许多 OOP 语言中,组件的隐藏不是自动的,也不是可以被覆盖的。因此,喜欢第二种定义的人将信息隐藏定义为一个单独的概念。

于 2013-06-19T08:32:08.113 回答
0

在您的示例中,这两种方法实际上没有区别。通常,属性使您可以将它们设置为只读其他类(使用私有设置器)-您将无法对该字段执行此类操作。公共字段/属性设置器打破了 OOP 的封装规则。

于 2013-06-19T08:35:12.557 回答
0

在 OOP 中,约定是对用户隐藏所有变量,并使用 Getter 和 Setter 来操作它们。在某些情况下,您需要更改变量值,直到它被保存。例如,您提示用户输入一些速度值,用户输入 MPH 中的值,但您希望将它们转换并存储为 Km/h 或 m/s。现在在这种情况下,使用 setter 是有意义的。在某些情况下,您希望 setter 或 getter 是私有的,以使变量只读或只写。但总结一下,在 OOP 约定中是使用 setter 和 getter 而不是公共变量。这是封装概念的一部分

于 2013-06-19T08:36:40.920 回答
0

你可以这样做,但这不是好的做法。将私有变量封装为属性意味着您可以更好地控制客户可以做什么和不可以做什么

如果它看起来有点冗长,你也可以使用以下

public string Name { get; set; }
于 2013-06-19T08:36:41.643 回答
0

正如 bash.d 所写,这是 OOP 的基础。

在这种情况下,我建议将名称放在构造函数中:

 class Person
 {

    public Person(string name)
    {
       this.myName = name;
    }

    private string myName ="N/A";
    public string Name
    {
        get 
        {
           return myName; 
        }
        private set 
        {
           myName = value; 
        }
    }

    public override string ToString()
    {
        return "Name = " + Name;
    }

    public static void Main()
    {
        Person person = new Person("Joe");
        Console.WriteLine("Person details - {0}", person);
        Console.WriteLine("Person details - {0}", person);

    }
 }

其他方法使用方法来设置值,您可以检查处理的对象。

于 2013-06-19T08:38:32.343 回答