繁体   English   中英

C# 中的自动属性是什么?它们的用途是什么?

[英]What are Automatic Properties in C# and what is their purpose?

有人可以对 C# 中的自动属性、它们的目的以及一些示例提供一个非常简单的解释吗? 请尽量用外行的话说!

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

public int SomeProperty { get; set; }

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

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

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

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

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

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 还提醒我:

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

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

虽然这就是我什至为我的内部程序所做的,但对于为公共使用而设计的程序(用于销售、开源等)来说,这可能更为重要。 如果您使用自动属性,然后决定需要在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)

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

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 );

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

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

希望这有所帮助。

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

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”,但它可能是其他非常相似的东西。 只要理解在那里,它可能并没有太大关系。 最后,无论如何它们都变成了内存地址:-)

它们只是一种编码快捷方式,可以节省程序员的几次按键操作。 而不是输入所有这些:

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

你可以输入:

public string LastName {
    get; set;
} 

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

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

public int SomeProperty { get; private set; }

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

来自自动实现的属性(C# 编程指南)

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

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

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

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

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

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

希望这可以帮助。

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

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

对于任何 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"

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

使用以下代码:

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);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM