【问题标题】:What are Automatic Properties in C# and what is their purpose?什么是 C# 中的自动属性,它们的用途是什么?
【发布时间】:2017-11-18 17:12:06
【问题描述】:

有人可以提供一个非常简单的 C# 中自动属性的解释,它们的用途,也许还有一些例子?请尽量保持通俗易懂!

【问题讨论】:

标签: c# .net syntax properties automatic-properties


【解决方案1】:

除了上一个答案中提到的方面,我还会注意到自动属性和字段之间的一些差异,因为它们看起来非常相似,并且它们的用法几乎相同:

  • 可以在需要时轻松开发为“经典”属性,而不会违反与属性调用者的任何合同
  • 在 Visual Studio 中开发时允许在 get/set 上设置断点。当通过反射完成更改并且更改的来源不明显时,这尤其有用

【讨论】:

    【解决方案2】:

    编辑:稍微扩展一下,这些用于使类中的私有变量更容易,但允许它们对类外部可见(不能修改它们)

    哦,自动属性的另一个优点是您可以在接口中使用它们! (不允许任何类型的成员变量)

    使用普通属性,您可以执行以下操作:

    private string example;
    public string Example 
    {
        get { return example; }
        set { example = value; }
    }
    

    自动属性允许您创建非常简洁的东西:

    public string Example { get; set; }
    

    所以如果你想创建一个只能在类中设置的字段,你可以这样做:

    public string Example { get; private set; }
    

    这相当于:

    private string example;
    public string Example 
    {
        get { return example; }
        private set { example = value; }
    }
    

    或者在 Java 中:

    private String example;
    
    public String getExample() {
        return example;
    }
    
    private void setExample(String value) {
        example = value;
    }
    

    编辑:@Paya 还提醒我:

    【讨论】:

    • 我还要添加这两个链接:MSDNASP.NET Blog
    • Java 中的 equivalent 需要 setExampleprivate 或根本不需要 setter。
    • 这应该是选择的答案,因为当前答案没有提供使用简单字段使用空 get/get over 的实际理由(突然说,它只是说明有一种简单的方法来声明无用的方法)。
    【解决方案3】:

    许多人已经说过自动属性是语法糖——一种编写简单属性的简写方式。我将处理公共变量和公共属性之间的差异,以及为什么在两者之间切换时需要重新编译。采取以下措施:

    public class MyClass
    {
        public int MyPublicVariable = 0;
    
        public int MyPublicProperty
        {
            get;
            set;
        }
    }
    

    一旦编译,概念上,它实际上最终类似于以下内容:

    public class MyClass
    {
        public int MyPublicVariable = 0;
    
        private int MyPublicProperty = 0;
    
        public int get_MyPublicProperty()
        {
            return MyPublicProperty;
        }
    
        public void set_MyPublicProperty( int value )
        {
            MyPublicProperty = value;
        }
    }
    

    很久以前,属性被发明为一种快速简便的方法来定义成对的 get 和 set 方法。它使代码更易读、更容易理解,因为它们传达了意图并确保了一致性。

    MyClass myClass = new MyClass();
    
    myClass.MyPublicVariable = 2;
    
    myClass.MyPublicProperty = 2;
    

    编译后,再次在概念上,它最终类似于以下内容:

    MyClass myClass = new MyClass();
    
    myClass.MyPublicVariable = 2;
    
    myClass.set_MyPublicProperty( 2 );
    

    因此,首选公共属性而不是公共变量的原因之一是,如果随着代码的发展需要使用不同的逻辑,那么代码的使用者不一定需要重新编译。这就是为什么它通常被认为是最佳实践。这也是发明自动属性的原因 - 在保持最佳实践的同时加快代码编写速度。

    还有一些关于接口的cmets。接口本质上是一种契约,它保证在任何实现它们的类中存在某些方法。从上面我们知道,属性代表一两个方法,所以它们在接口中工作得很好。

    希望这会有所帮助。

    这是另一个可能感兴趣的例子:

    public class MyClass
    {
        private int[] _myArray = new int[ 5 ];
    
        public int MyArray[ int index ]
        {
            get
            {
                return _myArray[ index ];
            }
            set
            {
                _myArray[ index ] = value;
            }
         }
    }
    
    public class MyClass
    {
        private int[] _myArray = new int[ 5 ];
    
        public int get_MyArray( int index )
        {
            return _myArray[ index ];
        }
    
        public void set_MyArray( int index, int value )
        {
            _myArray[ index ] = value;
        }
    }
    

    请注意:我记不清反编译时使用的方法签名 特性。我认为是 'get_XXX' 和 'set_XXX' 但它可能是 其他非常相似的东西。只要有理解, 这可能无关紧要。最后,无论如何它们都成为内存地址:-)

    【讨论】:

      【解决方案4】:

      使用以下代码:

      using System;
      
      class My Class
      {
          public string Dummy { get; set; }
      
          public My Class()
          {
              Dummy = "I'm dummy property";
          }
      }
      
      class Program 
      {
          static void Main() 
          {
                  var my Class = new My Class();
                   Console .Write Line (my Class .Dummy);
          }
      }
      

      【讨论】:

      • 我不确定这个答案是否添加了任何内容,因为它没有“对 C# 中的自动属性、它们的用途以及一些示例提供了非常简单的解释” ,它也无法编译。
      【解决方案5】:

      如果您问为什么要使用属性或自动属性,这就是它背后的设计理念。

      一个重要的设计原则是您从不公开字段,而是始终通过属性访问所有内容。这是因为您永远无法判断何时访问字段,更重要的是何时设置。现在,很多时候,在设置或获取值时不需要任何处理(例如,范围检查)。这就是创建自动属性的原因。它们是一种创建属性的简单的单行方式。它的后备存储由编译器创建。

      虽然这甚至是我为内部程序所做的事情,但对于为公众使用(用于销售、开源等)而设计的程序而言,这可能更为重要。如果您使用自动属性,后来又决定需要在 setget 中执行其他操作,则可以轻松更改代码而不会破坏公共接口。

      更新

      作为对下面评论的澄清点,如果所有代码都是您自己的,那么不,对您来说,属性和字段之间可能没有太大区别。但是,如果您正在设计一个将被其他人使用的库,那么在公共字段和属性之间来回切换将导致异常,除非首先重新编译使用该库的代码。

      作为测试,我创建了一个库项目并声明了一个名为TestData 的属性。我创建了一个全新的项目只是为了使用这个库。一切都按预期工作。然后我将该属性更改为公共字段(名称保持不变)并复​​制新的库 DLL,而无需重新编译使用项目。结果是抛出异常,因为代码期望找到方法属性方法get_TestDataset_TestData,但字段不是通过方法访问的。

      Unhandled Exception: System.MissingMethodException: Method not found: 'Void TestLibrary.TesterClass.set_TestData(System.String)'.
         at TestLibraryConsumer.Program.Main(String[] args)
      

      【讨论】:

      • "如果您使用自动属性,后来决定需要在 set 或 get 中执行其他操作,您可以轻松更改代码而不会破坏公共接口" .如果您稍后需要在赋值或读取之前进行一些处理,那么用同名属性替换字段同样容易。但在您需要此处理之前,声明属性与声明字段相比没有明显的好处。所以 OP 仍然有效(this answer 描述了拥有空 get/set 方法的实际好处)。
      • @mins。如果代码都是你的,那么你是对的。我已经更新了我的答案,以进一步阐明为什么在属性和字段之间翻转仍然会出错。
      【解决方案6】:

      对于任何 VB.NET 阅读器,其实现方式略有不同。例如:

      ''' <summary>The property is declared and can be initialized.</summary>
      Public Property MyProperty As String = "SomeValue"
      

      但是,关联字段可以通过以下划线前缀显式使用:

      Dim sConcat As String = _MyProperty + _MyProperty
      _MyProperty = sConcat
      

      在外部代码中:

      Dim sMyValue As String = oMyClassObj.MyProperty ' = "SomeValueSomeValue"
      

      就个人而言,我更喜欢这种方法,因为当您使用内部字段或可能暴露的属性时,您可以在使用代码中清楚地看到。

      【讨论】:

        【解决方案7】:

        简化接受的答案,您可以也使用

        public int SomeProperty { get; private set; }
        

        它具有相同的效果,您不再需要为此创建另一个变量。

        【讨论】:

        • 有趣的是,您仍然可以在构造函数中为public int SomeProperty { get; }(没有private set)设置一个值,就好像您的隐式支持字段被标记为readonly
        • 此建议适用于以下情况:您希望拥有一个只能被其他类“获取”的属性,并且能够通过此类中的其他方法对其进行更新。跨度>
        【解决方案8】:

        当属性访问器中不需要额外的逻辑时,使用自动属性。
        声明看起来像这样:

        public int SomeProperty { get; set; }
        

        它们只是语法糖,因此您无需编写以下更冗长的代码:

         private int _someField;
         public int SomeProperty 
         {
            get { return _someField;}
            set { _someField = value;}
         }
        

        【讨论】:

        • @Cody Gray @Stecya 为什么我不能只使用public int SomeProperty; 这不一样吗?我的意思是,如果这里根本没有私有变量,那我们为什么还需要属性呢?
        • @user2048204 因为属性不同于变量blog.codinghorror.com/properties-vs-public-variables
        • @user2048204 有一个私有变量;它是一个自动生成的匿名私有字段。但是您编写代码以通过公共属性名称从类中访问它(在功能上与直接访问它相同,在这种情况下,访问器上没有其他逻辑)。
        • 当你使用 ildasm 工具探索一个自动实现的属性时,你会知道在每个自动实现的属性后面都有一个自动创建的字段,一个私有数据成员和两个用作 getter 的方法并设置该私有字段。
        • Stecya/AustinWBryan 的回答中缺少一些东西。如果自动属性在幕后创建了一个私有字段,为什么接口可以定义自动属性但不能定义字段? autoproperties 不可能是“只是”语法糖,因为当我在接口中使用它们时会出现编译器错误。
        【解决方案9】:

        在早期版本的 C# 中,为了使用属性,您需要创建一个字段来保存值(称为备份存储):

        private string _something;
        public string Prop { get { return _something; } }
        

        从 C# 3.0 开始,不再需要此要求,编译器会自动为您创建后备存储,因此无需声明 _something 字段。

        您可以在此处阅读有关此问题的更多信息:http://msdn.microsoft.com/en-us/library/bb384054.aspx

        希望这会有所帮助。

        【讨论】:

        • 它是 C# 3.0 及更高版本。您链接到的文档在顶部说。
        【解决方案10】:

        它们只是为程序员节省几次击键的编码快捷方式。而不是输入所有这些:

        private string _lastName;
        public string LastName {
            get {
                return _lastName;
            }
            set {
                _lastName = value;
            }
        }  
        

        你可以输入:

        public string LastName {
            get; set;
        } 
        

        并让编译器自动生成其余部分。

        【讨论】:

        • 编译器还创建了一个私有的匿名支持字段,只能通过属性的 get 和 set 访问器访问。
        【解决方案11】:

        来自Auto-Implemented Properties (C# Programming Guide)

        在 C# 3.0 及更高版本中,当属性访问器中不需要额外的逻辑时,自动实现的属性使属性声明更加简洁。它们还使客户端代码能够创建对象。
        当您声明一个属性时,编译器会创建一个私有的匿名支持字段,该字段只能通过该属性的 get 和 set 访问器访问。

        class Person
        {
               public string Name { get; set; }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-10-24
          • 1970-01-01
          • 2017-02-23
          • 1970-01-01
          • 2010-09-27
          • 2011-12-17
          相关资源
          最近更新 更多