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

den*_*nis 59 .net c# syntax properties automatic-properties

有人可以提供C#中自动属性的简单解释,它们的用途,也许还有一些例子吗?请尽量保持外行的条件!

Ste*_*cya 76

如果属性访问器中不需要其他逻辑,则使用自动属性.
声明看起来像这样:

public int SomeProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

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

 private int _someField;
 public int SomeProperty 
 {
    get { return _someField;}
    set { _someField = value;}
 }
Run Code Online (Sandbox Code Playgroud)

  • @Cody Gray @Stecya为什么我不能只使用`public int SomeProperty;`这不一样吗?我的意思是如果这里根本没有私有变量,那为什么我们甚至需要属性呢? (11认同)
  • 令人惊讶的是,在这个帖子的 5 个回复中,没有人回答这个问题,即“为什么我们甚至需要属性”。他并不是在问它“在幕后”是如何工作的,而是问它的实际用途。我认为,当您没有实际理由使用属性(例如实现接口或使用反射)时,您确实最好将该字段公开并完成它。如果不对它们进行任何操作,则不需要 getter-setter。 (6认同)
  • @ user2048204因为属性不同于变量https://blog.codinghorror.com/properties-vs-public-variables/ (4认同)
  • 当您使用 ildasm 工具探索自动实现的属性时,您会知道在每个自动实现的属性后面都有以下字段自动创建一个私有数据成员和两个用作该私有字段的 getter 和 setter 的方法。 (2认同)
  • Stecya/AustinWBryan 的答案中缺少一些内容。如果自动属性在幕后创建私有字段,为什么接口可以定义自动属性但不能定义字段?自动属性不可能“只是”语法糖,因为当我在接口中使用它们时,会出现编译器错误。 (2认同)

Dar*_*lus 35

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

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

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

private string example;
public string Example 
{
    get { return example; }
    set { example = value; }
}
Run Code Online (Sandbox Code Playgroud)

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

public string Example { get; set; }
Run Code Online (Sandbox Code Playgroud)

因此,如果您想创建一个只能在类中设置的字段,您可以执行以下操作:

public string Example { get; private set; }
Run Code Online (Sandbox Code Playgroud)

这相当于:

private string example;
public string Example 
{
    get { return example; }
    private set { example = value; }
}
Run Code Online (Sandbox Code Playgroud)

或者在Java中:

private String example;

public String getExample() {
    return example;
}

private void setExample(String value) {
    example = value;
}
Run Code Online (Sandbox Code Playgroud)

编辑:@Paya还提醒我:

  • Java中的_equivalent_需要`setExample`为`private`或者根本不需要setter. (6认同)

Jim*_*Jim 14

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

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

虽然这就是我对内部程序的所作所为,但对于那些专为公共用途(销售,开源等)而言,它可能更为重要.如果您使用自动属性,然后决定需要在set或中执行其他操作,则get可以轻松更改代码而不会破坏公共界面.

  • @分钟。如果代码是您所有的,那么您是正确的。我已经更新了答案,以进一步阐明为什么在属性和字段之间切换仍然会出错。 (2认同)

Chr*_*ris 5

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

public class MyClass
{
    public int MyPublicVariable = 0;

    public int MyPublicProperty
    {
        get;
        set;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

MyClass myClass = new MyClass();

myClass.MyPublicVariable = 2;

myClass.MyPublicProperty = 2;
Run Code Online (Sandbox Code Playgroud)

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

MyClass myClass = new MyClass();

myClass.MyPublicVariable = 2;

myClass.set_MyPublicProperty( 2 );
Run Code Online (Sandbox Code Playgroud)

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

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

希望这有所帮助。

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

public class MyClass
{
    private int[] _myArray = new int[ 5 ];

    public int MyArray[ int index ]
    {
        get
        {
            return _myArray[ index ];
        }
        set
        {
            _myArray[ index ] = value;
        }
     }
}
Run Code Online (Sandbox Code Playgroud)
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;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意:我无法准确记住反编译属性时使用的方法签名。我认为它是“get_XXX”和“set_XXX”,但也可能是其他非常相似的东西。只要有理解,可能就没有那么重要了。无论如何,最终它们都变成了内存地址:-)