为什么我们需要C#中的属性

时间:2009-10-06 04:05:23

标签: c# .net properties

你能告诉我C#中属性的确切用法,我的意思是实用解释

在我们的项目中,我们使用的是

之类的属性
/// <summary>
/// column order
/// </summary>
protected int m_order;

/// <summary>
/// Get/Set column order
/// </summary>
public int Order
{
   get { return m_order; }
   set { m_order = value; }
}

/// <summary>
/// constructor
/// </summary>
/// <param name="name">column name</param>
/// <param name="width">column width</param>
/// <param name="order">column order</param>
public ViewColumn(string name, int width, int order)
{
   //
   // TODO: Add constructor logic here
   //
   m_name = name;
   m_width = width;
   m_order = order;
}  


/// <summary>
/// returns the column name, width, and order in list view.
/// </summary>
/// <returns>string represent of the ViewColumn object</returns>
public override string ToString()
{
  return (string.Format("column name = {0}, width = {1}, order = {2}.", 
        m_name, m_width, m_order));
}

/// <summary>
/// Do a comparison of 2 ViewColumn object to see if they're identical.
/// </summary>
/// <param name="vc">ViewColumn object for comparison</param>
/// <returns>True if the objects are identical, False otherwise.</returns>
public override bool Equals(object obj)
{
   ViewColumn vc = (ViewColumn)obj;
   if(m_name == vc.Name &&
        m_width == vc.Width &&
        m_order == vc.Order)
      return true;
   else
      return false;
}

8 个答案:

答案 0 :(得分:33)

简答:封装

答案很长:属性非常多才多艺。它允许您选择将数据公开给外部对象的方式。设置值时,可以注入一些数据验证。它还解决了Java等中出现的getX()setX()方法的问题。

答案 1 :(得分:24)

考虑一下:你有一个房间,你想要管理谁可以进入以保持房间的内部一致性和安全性,因为你不希望任何人进来并把它搞砸并留下它没有发生任何事情。因此,这个房间将是你实例化的课程,属性将成为人们进入房间的门。您在物业的设置者和吸气剂中进行适当的检查,以确保任何意外的事情进入和离开。

更多技术答案将是封装,您可以查看此答案以获取更多相关信息:https://stackoverflow.com/a/1523556/44852

class Room {
   public string sectionOne;
   public string sectionTwo;
}

Room r = new Room();
r.sectionOne = "enter";

人们很容易进入sectionOne,没有任何检查。

class Room 
{
   private string sectionOne;
   private string sectionTwo;

   public string SectionOne 
   {
      get 
      {
        return sectionOne; 
      }
      set 
      { 
        sectionOne = Check(value); 
      }
   }
}

Room r = new Room();
r.SectionOne = "enter";

现在你检查了那个人并且知道他是否有邪恶的东西。

答案 2 :(得分:16)

很多原因:

  • 语义。属性将您的类型的实现与接口分开。
  • 二进制兼容性。如果您需要更改属性,则可以在不破坏相关代码的二进制兼容性的情况下执行此操作。对于字段,即使新实现使用具有相同名称的属性,也必须重新编译所有内容
  • 数据绑定。你无法数据绑定到一个字段。

答案 3 :(得分:7)

这是一个常见的模式:

class Foo {

    private Bar _bar;

    //here, Foo has a Bar object.  If that object has already been instantiated, return that value.  Otherwise, get it from the database.
    public Bar bar {
        set { _bar = value;}
        get {
            if (_bar == null) {
                _bar = Bar.find_by_foo_name(this._name);
            }
            return _bar;
        }
    }
}

简而言之,这允许我们访问Foo实例上的Bar对象。这种封装意味着我们不必担心如何检索Bar,或者是否已经实例化了foo.bar。我们可以使用该对象,让Foo类的内部处理它。

答案 4 :(得分:5)

设计时间优势

属性使视觉设计变得简单,您可以使用Visual Studio的最着名的属性浏览器来更改对象的属性。

属性还提供了额外的验证元数据,即属性浏览器中的视觉外观,如下拉列表,范围,颜色选择器等。

单独的数据和操作

它们真实地表示对象的“数据”与对象的“动作”(方法)之间的差异。

当我们看课时,如果我们有50个方法可以看,不是每个人都会使用正确的函数命名,这将使以后难以理解。我总是告诉程序员,无论何时编程,都要以这样的方式编写代码:5年后,如果其他人查看代码,他应该理解代码。

使用数据访问的方法名称和某些操作从长远来看会产生混淆......就像Stack一样,Push / Pop是动作,但“Size”或“Count”是数据。

创建“Count”属性只是将其目的区分为数据而不是行动。

<强>数据绑定

正如其他人所提到的,属性提供了高级数据绑定,如双向绑定等。

访问限制

您可以拥有其他人提及的只读属性和其他访问者。

<强>反射

在编写基于反射的通用代码时,很容易使用属性。

不同的存储实施

公共变量仅将数据存储为成员,其他属性提供了以不同形式存储数据的各种方式,例如internaly,它们可以存储为哈希表(因为它们在WPF中的依赖项对象中完成)。它们可以缓存。它们可以进一步转发给其他一些子实体或外围实体。但是,对于呼叫者隐藏了实现。

<强>验证

设置属性可能需要进行某些验证,“设置”部分代码中的验证代码可以轻松帮助您验证输入并相应地报告错误。

通知

设置方法的一部分可以引发其他对象可以监听的INotifyPropertyChanged.PropertyChanged等通知事件,并更新显示值。这是高级数据绑定的重要部分。

简而言之,它是一个新的“标准”数据存储,具有先进的设施,然后只是将数据存储在类成员中。通常避免使用属性,您可以执行所有功能,但由于实现可能因人而异,因此它是一个标准,可帮助每个人在一个名为“Properties”的表单中定义/访问/验证/通知数据存储

答案 5 :(得分:4)

这是使用它的方式,除了你设置它的方式,可能。您可能希望在类中使用该属性,而不是访问成员变量,因此您可以使用有关每个成员变量的统一规则。这是使用属性的主要优点,是将访问和设置器逻辑全部集中到一个地方。这取决于您的具体需求,无论您是否想要使用该属性进行设置。但请注意,在构造函数中,您在调用Property时要非常小心,因为您可能会或可能不会依赖于正在初始化的类的其他部分,如果通过构造函数访问它们将无法完成。同样,这取决于您的具体实施。

使用它也更清洁:

myObject.Property1 = "Test String";
Console.WriteLine(myObject.Property1);

比你在其他一些语言中看到的那样:

myObject.setProperty1("Test String");
System.out.writeln(myObject.getProperty1());

在这种情况下,您可以封装一些逻辑:

public int Order
{
    get { return m_order; }
    set
    {
        // Put some rules checking here. Maybe a call to make sure that the order isn't duplicated or some other error based on your business rules.
        m_order = value;
    }
}

他们有用的另一种方式是:

public int Order { get; private set; }

现在你有一个自动实现的属性,它有一个支持成员变量,只能在类中设置,但在其他地方读取。

最后,如果你需要控制逻辑,你可以这样写:

public int Order
{
    get { return m_order; }
    protected set
    {
        // Again, you can do some checking here if you want...
        m_order = value;
        // You can also do other updates if necessary. Perhaps a database update...
    }
}

答案 6 :(得分:4)

Justin指出,封装是OOP的基本原则之一。您可能希望将类中的数据的内部表示从外部隐藏起来,并提供经过批准的查看/操作方法。

C#属性是一种提供简单方法的构造。在您的示例中,您没有在getset方法中执行任何操作,但在现实生活中,您可能需要执行某些操作,例如

  • 将货币存储在十分之一美分中作为一个长整数,但作为一个带有2个小数位和$符号的字符串返回外部世界。
  • 将某个属性限制为只读(甚至只写:对于ex:,密码验证器/哈希生成器类)。
  • 设置/获取此值时,以某种方式更改对象的状态。

在Java中,您编写的getter和setter是分别返回或接受值的普通方法。

答案 7 :(得分:4)

属性用于限制对类的成员变量的直接访问。 使用属性维护抽象。 每当您想要实例化一个对象并使用属性将数据设置为它的成员变量时,您可以检查某些条件是否将该值设置为成员变量。 您可以限制对属性的读写,以便在访问该类的对象时可以只读取成员变量的值。