【问题标题】:C# basic property understandingC#基本属性理解
【发布时间】:2013-08-07 01:44:04
【问题描述】:

我正在学习 C#,我遇到了下面这段代码

public class Album
{
     public virtual int AlbumId { get; set; }
     public virtual int GenreId { get; set; }
     public virtual int ArtistId { get; set; }
     public virtual string Title { get; set; }
     public virtual decimal Price { get; set; }
     public virtual string AlbumArtUrl { get; set; }
     public virtual Genre Genre { get; set; }
     public virtual Artist Artist { get; set; }
}

只是想知道以下内容有什么不同?我的意思是没有 get 和 set 你也可以访问这些公共财产。是什么让这些 get 和 set 变得重要?

public class Album
{
    public virtual int AlbumId;
    public virtual int GenreId;
    public virtual int ArtistId;
    public virtual string Title;
    public virtual decimal Price;
    public virtual string AlbumArtUrl;
    public virtual Genre Genre;
    public virtual Artist Artist;
}

【问题讨论】:

标签: c#


【解决方案1】:

控制您的对象私有字段值。例如,如果您不想让整数使用空值或负值。

bool started;
    public bool Started
    {
        get { return started; }
        set
        {
            started = value;
            if (started)
                OnStarted(EventArgs.Empty);
        }

    }
another example

    int positiveNumber;

    public int PositiveNumber
    {
        get { return positiveNumber; }
        set {
            if (value < 0)
                positiveNumber = 0;
            else positiveNumber = value;
        }
    }

只读属性的另一种实现方式如下

   int positiveNumber;

    public int PositiveNumber
    {
        get { return positiveNumber; }

    }

【讨论】:

  • 感谢这个有意义
【解决方案2】:

你不能声明一个虚拟字段

public class Album
{
  public virtual int AlbumId; // <- Syntax error
...
}

属性实际上是方法:get or(and) set,所以

public class Album
{
     public virtual int AlbumId { get; set; } // <- Both get and set methods declared as virtual ones
  ...
}

如果需要,您可以在派生类中覆盖这些 get 或(和)set:

public class GreatAlbum: Album {
    private Boolean m_IsGreat;  

    public override int AlbumId {
      get {
        if (m_IsGreat) 
          return base.AlbumId
        else
          return 0; 
      } 
      set {
        m_IsGreat = (value != 0);

        base.AlbumId = value;
      }
    }
  ... 
}

【讨论】:

  • 但是设置属性和直接使用像classname.variablename这样的值有什么区别???
  • @M.N.S:从技术上讲,语法是相同的,但在底层存在一些差异。例如,在您的情况下(虚拟属性),您可以在派生类中覆盖它(请参阅我的编辑)。
  • 不,不,忘了virtual和all,如果albuid等是在公共类中公开定义的,那么通过继承我们也可以像classname.variablename一样直接访问它们。那为什么要使用属性呢?有什么具体的好处???
  • 通常我们使用属性来限制访问(例如,当 get 是 public 时,set 是 protected 或 private);对于复杂的输出(get),例如如果 Title 为 null 或为空,我们将 AlbumId 返回为 0;用于验证(设置),例如您可以在尝试为 AlbumId 设置负值时抛出异常;对于接口实现 - 您可以将属性放入接口(属性是一种方法),但不能放入字段;对于多态行为 - 您可以设置属性,但不能设置字段是虚拟的
【解决方案3】:

通过提供 get(accessor) 和 set(mutator) 方法,您可以控制访问和变异。 例如:

您有一个属性,您不想将其设置为超过 15 的任何值。因此,您在 set 方法中进行了必要的限制。除非那个 set 方法,否则你无法控制。

但在你的例子中,你的 get 和 set 方法是默认的,意味着什么都不控制。

【讨论】:

    【解决方案4】:

    属性背后的主要原因是以受控方式保护和呈现私人数据。

    实际上,属性在使用中显示了它们的能力:

    public virtual int AlbumId 
    { 
        get { // ... some magical operations ... }
        set { // ... some magical operations ... }
    }
    

    关于你的主要问题——这个例子有什么不同——要注意的重点是virtual关键字。

    这个关键字导致属性是可覆盖的,因此任何其他代码都可以覆盖默认的get; 方法。这意味着您拥有自己的默认行为,而其他代码(在实体框架中非常使用)实现了自己的逻辑!

    您示例中的第二个不是属性,因此它们没有表达这种神奇的能力......!

    【讨论】:

      【解决方案5】:

      在第一种情况下,您处理的是属性,在第二种情况下,您处理的是字段。

      与使用属性相比,使用字段有几个缺点。这些缺点包括:

      1. 您可以在属性的getset 中设置断点,但不能在访问字段时设置断点。
      2. 公开字段违反了信息隐藏原则。
      3. 用于访问字段和属性的二进制 MSIL 代码是不同的,因此如果您将来将公共字段更改为公共属性,尽管源代码保持兼容,但任何依赖的二进制代码都会中断。
      4. 使用反射所需的代码不同,因此当您从字段移动到属性时,您的反射代码会中断。

      长话短说:始终使用公共属性,从不使用公共字段。

      【讨论】:

        【解决方案6】:

        有许多不同之处:

        • 编译器将属性转换为方法。因此,您可以将它们声明为虚拟并在派生类中覆盖它们。
        • 使用属性,您可以将逻辑放入 getter 或 setter(过滤、验证等)。
        • 当您使用自动实现的属性 ({ get;set;}) 时,您似乎还不如只使用公共字段。但是,使用属性意味着您可以在以后更改您的 getter 或 setter 实现,而无需更改您的类公开的接口。如果您使用了一个字段,并希望在读取该字段时实现过滤,则必须引入一种新方法,将该字段设为私有并破坏该类型的所有现有使用者。

        就个人而言,我认为自动实现的属性会促进不良风格,因为它们不鼓励封装。 ReSharper 等工具也喜欢使用 {get;set} 访问器生成属性。因此,新手开发人员通常最终会得到具有大量 {get;set;} 属性的类,这些属性将类型的状态暴露给世界。您至少应该默认使用{get; private set;}

        【讨论】:

          猜你喜欢
          • 2010-12-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多