C#中的{get; set;}语法是什么?

我正在学习ASP.NETMVC,我可以阅读英文文档,但我真的不明白这段代码中发生了什么:

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

{ get; set; }是什么意思?

1439103 次浏览

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

您可以使用它们来获取/设置Genre实例中该属性的值。

这些是自动属性

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

public class Genre
{
private string _name;


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

这意味着,如果您创建类型为Genre的变量,您将能够将该变量作为属性访问

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

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

您可以在MSDN的自动实现的属性编程指南上阅读更多信息。

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

private string name;
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}

这是这样做的简短方法:

public class Genre
{
private string _name;


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

这是将数据成员公开为公共的快捷方式,因此您无需显式创建私有数据成员。C#将为您创建一个私有数据成员。

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

这样的{ get; set; }语法称为自动属性,C#3.0语法

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

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

因此,据我所知,{ get; set; }是一个“自动属性”,就像@Klaus和@Brandon所说的那样,它是编写具有“支持字段”的属性的简写。

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访问器,这意味着它们能够访问私人字段中的数据和信息(通常来自支持字段),并且通常来自公共属性(如上例所示)。

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

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)

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

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

g1.Name = "Hip Hop";

这里发生的事情有点复杂。就像我之前说的,getset从私有字段访问信息,否则您将无法访问这些信息。get只能从该私有字段中阅读信息并返回它。set只能在该私有字段中信息。但是通过同时具有getset的属性,我们可以同时执行这两个函数。通过编写g1.Name = "Hip Hop";,我们专门使用了Name属性中的set函数

set使用了一个名为value的隐式变量。基本上,这意味着每当您在set中看到“值”时,它都指的是一个变量;“值”变量。当我们编写g1.Name =时,我们使用=传入value变量,在这种情况下是"Hip Hop"。所以你可以这样想:

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实例的名称,我相信我们可以通过编写收到的名称

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"

因此,为了这个解释的目的,我也将完成带有输出的示例

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

输出:

"Genres: Hip Hop, Rock, Country"

基本上,它是一个快捷方式:

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

在Visual Studio中,如果您在类中定义属性X并且您只想将此类用作类型,则在构建项目后,您将收到“字段X永远不会分配给,并且将始终具有其默认值”的警告。

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

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

在此处输入图片描述

当属性出现在右侧时调用Get(RHS) 当属性出现在左侧时调用Set(LHS) 的'='符号

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

示例:

public string Log { get; set; }

而对于非自动实现的属性,支持字段是前期的,作为私有范围的变量可见。

示例:

private string log;


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

另外,这里值得注意的是'getter'和'setter'可以使用不同的'支持字段'

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

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

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

它基本上是一种速记。您可以像许多示例中一样编写public string Name { get; set; },但您也可以编写它:

private string _name;


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

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

让我给你举个例子:

private class Person {
private int _age;  // Person._age = 25; will throw 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”

定义私有变量

在构造函数内部并加载数据

我已经创建了常量并将数据从常量加载到选择列表类。

public  class GridModel
{
private IEnumerable<SelectList> selectList;
private IEnumerable<SelectList> Roles;


public GridModel()
{
selectList = from PageSizes e in Enum.GetValues(typeof(PageSizes))
select( new SelectList()
{
Id = (int)e,
Name = e.ToString()
});


Roles= from Userroles e in Enum.GetValues(typeof(Userroles))
select (new SelectList()
{
Id = (int)e,
Name = e.ToString()
});
}


public IEnumerable<SelectList> Pagesizelist { get { return this.selectList; } set { this.selectList = value; } }
public IEnumerable<SelectList> RoleList { get { return this.Roles; } set { this.Roles = value; } }
public IEnumerable<SelectList> StatusList { get; set; }


}

属性就像一个层,将私有变量与类的其他成员分开。从外部世界看,属性只是一个字段,可以使用访问属性。属性

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


public string LastName { get; set; }


public string FullName => $"{FirstName} {LastName}";
}


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


public string LastName { get; set; }


public string FullName { get { return $"{FirstName} {LastName}"; } }
}

FullName是一个属性。带箭头的是快捷方式。从外部世界,我们可以像这样访问FullName:

var person = new Person();
Console.WriteLine(person.FullName);

调用者不关心你如何实现FullName。但是在类中,你可以随心所欲地更改FullName。

查看Microsoft文档以获取更详细的解释:

https://learn.microsoft.com/en-us/dotnet/csharp/properties

基本上它有助于保护您的数据。考虑这个没有setter和getter的示例,以及与它们相同的示例。

没有setter和getter

班级学生

using System;
using System.Collections.Generic;
using System.Text;


namespace MyFirstProject
{
class Student
{
public string name;
public string gender;
public Student(string cName, string cGender)
{
name = cName;
gender= cGender;
}


}
}

在主

 Student s = new Student("Some name", "Superman"); //Gender is superman, It works but it is meaningless
Console.WriteLine(s.Gender);

用setters和getters

using System;
using System.Collections.Generic;
using System.Text;


namespace MyFirstProject
{
class Student
{
public string name;
private string gender;
public Student(string cName, string cGender)
{
name = cName;
Gender = cGender;
}


public string Gender
{
get { return gender; }
set
{
if (value == "Male" || value == "Female" || value == "Other")
{
gender = value;
}
else
{
throw new ArgumentException("Invalid value supplied");
}
}
}
}
}

在主:

  Student s = new Student("somename", "Other"); // Here you can set only those three values otherwise it throws ArgumentException.
Console.WriteLine(s.Gender);

属性是用于封装数据的函数,并允许每次检索或修改值时执行额外的代码。

与C++不同,VB. Net或Objective-C没有一个用于声明属性的关键字,而是使用两个关键字(get/set)来提供用于声明函数的缩写语法。

但是拥有属性是很常见的,这并不是因为你想在检索或修改数据时运行额外的代码,而是因为你可能想在将来这样做,或者有一个合同规定此值必须作为属性公开(C#不允许通过接口将数据公开为字段)。这意味着即使是函数的缩写语法也比需要的更冗长。意识到这一点,语言设计者决定为这个典型的用例进一步缩短语法,并添加了“自动”属性,这些属性只需要最低限度,即封闭的大括号,以及两个关键字中的任何一个(使用两个关键字时用分号分隔)。

在VB. Net中,这些“自动”属性的语法长度与c#--Property X as String vsstring X {get; set;}相同,两种情况都为20个字符。它之所以如此简洁,是因为在正常情况下它实际上需要3个关键字,而在自动属性的情况下可以不需要2个关键字。

从任何一个中删除更多,并且必须添加一个新的关键字,或者附加到符号或空白的意义。