关于属性:什么是{get;

What is the { get; set; } syntax in C#?

我正在学习ASP.NET MVC,我可以阅读英文文档,但我不太了解此代码的情况:

1
2
3
4
public class Genre
{
    public string Name { get; set; }
}

这是什么意思:{ get; set; }


它是所谓的自动属性,本质上是以下内容的简写(类似的代码将由编译器生成):

1
2
3
4
5
6
7
8
9
10
11
12
private string name;
public string Name
{
    get
    {
        return this.name;
    }
    set
    {
        this.name = value;
    }
}


据我所知,{ get; set; }是一种"汽车属性",就像@klaus和@brandon所说的"汽车属性",是用"支持字段"编写属性的简写,因此在这种情况下:

1
2
3
4
5
6
7
8
9
public class Genre
{
    private string name; // This is the backing field
    public string Name   // This is your property
    {
        get => name;
        set => name = value;
    }
}

然而,如果你像我一样——大约一个小时前——你并不真正了解什么是属性和访问器,你也不太了解一些基本术语。msdn是一个很好的学习工具,但是对于初学者来说,它并不总是容易理解的。所以我会在这里更深入地解释这一点。

getset是访问器,这意味着它们能够访问私有字段(通常是从支持字段)中的数据和信息,并且通常是从公共属性(如上述示例中所示)访问的。

不可否认,上面的陈述非常令人困惑,所以让我们来看一些例子。假设这个代码是指音乐的流派。所以在课堂类型中,我们需要不同类型的音乐。假设我们想要三种类型:嘻哈、摇滚和乡村音乐。为此,我们将使用类的名称来创建该类的新实例。

1
2
3
4
5
6
7
8
Genre g1 = new Genre(); //Here we're creating a new instance of the class"Genre"
                        //called g1. We'll create as many as we need (3)
Genre g2 = new Genre();
Genre g3 = new Genre();

//Note the () following new Genre. I believe that's essential since we're creating a
//new instance of a class (Like I said, I'm a beginner so I can't tell you exactly why
//it's there but I do know it's essential)

现在我们已经创建了流派类的实例,我们可以使用上面设置的"name"属性设置流派名称。

1
2
public string Name //Again, this is the 'Name' property
{ get; set; } //And this is the shorthand version the process we're doing right now

我们可以通过编写以下内容将"g1"的名称设置为hip hop

1
g1.Name ="Hip Hop";

这里发生的事情有点复杂。如我之前所说,getset从私有字段访问信息,否则您将无法访问这些信息。get只能从该私有字段中读取信息并将其返回。set只能在该私有字段中写入信息。但是通过拥有一个同时拥有getset的财产,我们可以同时完成这两个功能。通过编写g1.Name ="Hip Hop";,我们专门使用名称属性中的set函数。

set使用一个称为value的隐式变量。基本上,这意味着当你在set中看到"value"时,它指的是一个变量,"value"变量。当我们编写g1.Name =时,我们使用=来传递value变量,在本例中是"Hip Hop"变量。所以你基本上可以这样想:

1
2
3
4
5
6
7
8
9
10
11
public class g1 //We've created an instance of the Genre Class called"g1"
{
    private string name;
    public string Name
    {
        get => name;
        set => name ="Hip Hop"; //instead of 'value',"Hip Hop" is written because
                              //'value' in 'g1' was set to"Hip Hop" by previously
                              //writing 'g1.Name ="Hip Hop"'
    }
}

需要注意的是,上面的示例实际上不是用代码编写的。它更像是一个假设性的代码,它代表了在后台发生的事情。

既然我们已经设置了g1类型实例的名称,我相信我们可以通过编写

1
2
3
console.WriteLine (g1.Name); //This uses the 'get' function from our 'Name' Property
                             //and returns the field 'name' which we just set to
                             //"Hip Hop"

如果我们运行这个,我们将在控制台中得到"Hip Hop"

因此,为了这个解释的目的,我将用输出来完成这个例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
public class Genre
{
    public string Name { get; set; }
}

public class MainClass
{
    public static void Main()
    {
        Genre g1 = new Genre();
        Genre g2 = new Genre();
        Genre g3 = new Genre();

        g1.Name ="Hip Hop";
        g2.Name ="Rock";
        g3.Name ="Country";

        Console.WriteLine ("Genres: {0}, {1}, {2}", g1.Name, g2.Name, g3.Name);
    }
}

输出:

1
"Genres: Hip Hop, Rock, Country"


这些是自动属性

基本上是用支持字段编写属性的另一种方法。

1
2
3
4
5
6
7
8
9
10
public class Genre
{
    private string _name;

    public string Name
    {
      get => _name;
      set => _name = value;
    }
}


这是实现这一目标的捷径:

1
2
3
4
5
6
7
8
9
10
public class Genre
{
    private string _name;

    public string Name
    {
      get => _name;
      set => _name = value;
    }
}

它是将数据成员公开为公共的快捷方式,这样您就不需要显式地创建私有数据成员。C将为您创建一个私有数据成员。

您可以在不使用此快捷方式的情况下公开数据成员,但如果您决定将数据成员的实现更改为具有某些逻辑,则需要中断接口。所以简而言之,这是创建更灵活代码的捷径。


基本上,这是一个捷径:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Genre{
    private string genre;
    public string getGenre() {
        return this.genre;
    }
    public void setGenre(string theGenre) {
        this.genre = theGenre;
    }
}
//In Main method
genre g1 = new Genre();
g1.setGenre("Female");
g1.getGenre(); //Female


它是C_的自动实现属性。


这是自动实现的属性。这基本上是在C中为类创建属性的一种简略方法,而不必为它们定义私有变量。当获取或设置变量值时不需要额外的逻辑时,通常使用它们。

您可以阅读更多关于msdn的自动实现属性编程指南。


它们是公共属性名称的访问器。

您将使用它们来获取/设置流派实例中该属性的值。


这意味着,如果创建一个类型为tyre的变量,则可以将该变量作为属性访问

1
2
Genre oG = new Genre();
oG.Name ="Test";


  • get/set模式提供了一种结构,允许在实例化类的属性实例的设置("set")或检索("get")期间添加逻辑,这在属性需要某些实例化逻辑时非常有用。

  • 属性只能有"get"访问器,这样做是为了使该属性为只读

  • 在实现get/set模式时,中间变量被用作一个容器,其中可以放置一个值并提取一个值。中间变量通常以下划线作为前缀。此中间变量是私有的,以确保只能通过其get/set调用访问它。请参阅Brandon的答案,因为他的答案演示了实现get/set最常用的语法约定。


在Visual Studio中,如果在类中定义一个属性X,并且只希望将该类用作类型,则在构建项目之后,将收到一条警告,提示"字段x从未赋值,并且始终具有其默认值"。

通过向X属性中添加{ get; set; },您将不会收到此警告。

此外,在Visual Studio 2013和更高版本中,通过添加{ get; set; },您可以看到对该属性的所有引用。

enter image description here


这种{ get; set; }语法称为自动属性,即C 3.0语法。

必须使用Visual C 2008/CSC v3.5或更高版本进行编译。但您可以编译目标为.NET Framework 2.0的输出(不需要运行时或类来支持此功能)。


get set是属性的访问修饰符。get读取属性字段。set设置属性值。get就像只读访问。设置类似于只写访问。要将属性用作读写,必须同时使用get和set。


基本上是个速记。您可以编写公共字符串名称get;set;,类似于许多示例,但也可以编写它:

1
2
3
4
5
6
7
private string _name;

public string Name
{
    get { return _name; }
    set { _name = value ; } // value is a special keyword here
}

为什么要使用它?它可以用来过滤对属性的访问,例如,您不希望名称中包含数字。

让我举个例子:

1
2
3
4
5
6
7
8
9
10
private class Person {
    private int _age;  // Person._age = 25; will through an error
    public int Age{
        get { return _age; }  // example: Console.WriteLine(Person.Age);
        set {
            if ( value >= 0) {
                _age = value; }  // valid example: Person.Age = 25;
        }
    }
}

官方称之为自动实现的属性和它阅读(编程指南)的好习惯。我还推荐教程视频C属性:为什么使用"get"和"set"。


当属性出现在右侧(rhs)时调用get当属性出现在左侧(lhs)时调用set"="符号

对于自动实现的属性,支持字段在场景后面工作,不可见。

例子:

1
public string Log { get; set; }

而对于非自动实现的属性,支持字段是预先的,可以作为私有范围变量看到。

例子:

1
2
3
4
5
6
7
private string log;

public string Log
{
    get => log;
    set => log = value;
}

另外,这里值得注意的是"getter"和"setter"可以使用不同的"backing field"。