C# 速记 getter 和 setter
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8871757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The C# Shorthand getters and setters
提问by user962206
How does the Setters and Getters in C# implement Encapsulation? I am not new when it comes to these setters and getters, I have background with programming, specifically java. in java you use setters and getters like this
C#中的Setter和Getter是如何实现封装的?我对这些 setter 和 getter 并不陌生,我有编程背景,特别是 java。在 Java 中,您可以像这样使用 setter 和 getter
public class Person {
private String fName;
public void setName(String someName) {
fName = someName;
}
public String getName() {
return fName;
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.setName("Bob");
System.out.println(p.getName());
}
}
And in C# Using Shorthand
在 C# 中使用速记
public class Person {
public string fName{ get; set;}
}
How does the C# shorthand getters and setters implement encapsulation on this? how do I implement that C# code the same as the java code above? are there any restrictions regarding it? and base from my observation, I can only use that "fName" if its set to public, specifically "public string fName{ get; set;}" but when it comes to private I cannot. but when i set it to private, I can no longer access it in other methods.
C# 速记 getter 和 setter 是如何对此实现封装的?我如何实现与上面的 java 代码相同的 C# 代码?有什么限制吗?根据我的观察,我只能使用“fName”,如果它设置为 public,特别是“public string fName{ get; set;}”,但是当涉及到私有时,我不能。但是当我将它设置为私有时,我无法再通过其他方法访问它。
采纳答案by Chris Shain
They don't allow you to specify encapsulating behavior. What they do is allow you to specify that this is a Property in the public interface of your class, as opposed to a field.
它们不允许您指定封装行为。他们所做的是允许您在类的公共接口中指定这是一个属性,而不是一个字段。
The difference here is that in Java, getters and setters are simply methods that follow a certain convention (getXXX, setXXX). In C#, properties are a first-class construct (even though they are basically getters and setters behind the scenes). So C# provides these as a shorthand way of saying you might implement encapsulation later (e.g. add behavior to the getter or setter) but you don't want to break consumers of your class, so you are declaring them as properties up front.
这里的区别在于,在 Java 中,getter 和 setter 只是遵循特定约定(getXXX、setXXX)的方法。在 C# 中,属性是一流的构造(即使它们基本上是幕后的 getter 和 setter)。因此,C# 提供这些作为一种速记方式,表示您可以稍后实现封装(例如,将行为添加到 getter 或 setter),但您不想破坏类的使用者,因此您预先将它们声明为属性。
In Java:
在 Java 中:
public class Foo {
private String fooName;
public String BarName;
public String getFooName() { return fooName; }
public String setFooName(String fooName) { this.fooName = fooName; }
}
In C#:
在 C# 中:
public class Foo {
public String FooName { get; set; }
public String BarName;
}
Lets assume you have a consumer class FooReader defined in another assembly that references the Foo assembly:
假设您在另一个引用 Foo 程序集的程序集中定义了一个消费者类 FooReader:
public class FooReader {
public String ReadFoo(Foo foo) {
// This returns the Foo **property**
return foo.FooName;
}
public String ReadBar(Foo foo) {
// This returns the Bar **field**
return foo.BarName;
}
}
Now, changing Foo to this doesn'tbreak FooReader:
现在,将 Foo 更改为此不会破坏 FooReader:
public class Foo {
private String _fooName;
public String FooName { get { return _fooName.ToUpper(); } set { _fooName = value; } }
public String BarName;
}
but changing Foo to this WILLbreak FooReader- you'll need to recompile it:
但是将 Foo 更改为此将破坏 FooReader-您需要重新编译它:
public class Foo {
private String _fooName;
private String _barName;
public String FooName { get { return _fooName.ToUpper(); } set { _fooName = value; } }
// This breaks FooReader because you changed a field to a property
public String BarName { get { return _barName.ToUpper(); } set { _barName = value; } }
}
回答by Femaref
As you say yourself, the C# version is a shorthand for the following:
正如您自己所说,C# 版本是以下内容的简写:
private string _name;
public Name
{
get { return _name; }
set { _name = value; }
}
(Note that the private field isn't accessable, it's compiler generated. All your access will be via the property, even from inside the class)
(请注意,私有字段不可访问,它是编译器生成的。您的所有访问都将通过该属性进行,即使是在类内部)
In comparision to java, where getter/setter are simply methods, this construct is called a property in C#, and is a compiler feature.
与 java 中的 getter/setter 只是方法相比,此构造在 C# 中称为属性,并且是编译器功能。
回答by Jeremy Wiggins
In, C# the equivalent of the code inside your Person class would be:
在 C# 中,Person 类中的代码等效于:
private String _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
As of C# 3, you can condense that down to:
从 C# 3 开始,您可以将其浓缩为:
public string Name { get; set; }
This is an automatically implemented propertyand the compiler will automatically generate the same encapsulating code as it will if you were to write it out the long way. A private backing field is automatically generated for you, as well as the getand setmethods. Really, once the compiler generates the IL code, what you'll have is a field with two methods, get_Nameand set_Name, so by using the auto-implemented property, you're letting the compiler generate nearly the same code as you have in your java example.
这是一个自动实现的属性,编译器将自动生成与您长时间编写它时相同的封装代码。会自动为您生成一个私有支持字段,以及get和set方法。真的,一旦编译器生成的IL代码,你就必须是一个有两个方法,一个字段,get_Name并且set_Name,所以通过使用自动实现的属性,你让编译器生成几乎相同的代码,你在你的java有例子。
回答by Jens Bodal
I'm going to modify your question slightly to provide a better comparison. In Java you commonly have public getters and private setters, with the constructor being the initializor[sic] of the variable, such as:
我将稍微修改您的问题以提供更好的比较。在 Java 中,您通常有公共 getter 和私有 setter,构造函数是变量的初始化器 [sic],例如:
public class Person{
private String fName;
public Person (String name) {
setName(name);
}
private void setName(String someName){
fName = someName;
}
String getName(){
return fName;
}
}
With a user of the class only being able to retrieve the value after initialization through the constructor:
类的用户只能在通过构造函数初始化后检索值:
public class Example {
Person person = new Person("Fred");
System.out.println(person.getName()); // Allowed
System.out.println(person.fName); // Not allowed because fName is a local class variable
person.setName("Aaron"); // Not allowed because setName() is a local class method
}
Now this is where C# can become confusing, as instead of using Person.getNameyou simply use the variable itself, however this variable canstill be encapsulated. In Java you are taught that Class variables should be local (private) and should only be accessed with getters and setters. C# is essentially the same, but the syntax and logic is different. Rewriting my example in C# would be:
现在,这是C#就会变得更加复杂,因为不是使用Person.getName只需使用变量本身,但是这个变量可以仍然被封装。在 Java 中,你被教导类变量应该是本地的(私有的)并且只能通过 getter 和 setter 访问。C#本质上是一样的,只是语法和逻辑不同。用 C# 重写我的例子是:
public class Person {
public String fName {get; private set;}
public Person(String name) {
this.fName = name;
}
}
public class Example {
Person person = new Person("Fred");
Console.WriteLine(person.fName); // This is allowed
person.fName = "Tony"; // Not allowed because setter is private
}
Now if you wanted to add logic to your getter and setter using the above conventions, you would need to introduce a local private variable, but the code in Exampleand your Person constructor wouldn't change:
现在,如果您想使用上述约定向 getter 和 setter 添加逻辑,则需要引入一个本地私有变量,但其中的代码Example和您的 Person 构造函数不会更改:
class Person {
private String _fName;
public String fName {
get { return _fName + ".addedText"; }
private set { _fName = value.ToLower(); }
}
public Person(String fName) {
this.fName = fName;
}
}
Now whether this is better or worse than Java is somewhat debatable, but from what I've seen your code is going to be out of place in C# if you do something like the below, although syntax wise it will work:
现在,这是否比 Java 更好或更差有些值得商榷,但是从我所看到的,如果您执行以下操作,您的代码将在 C# 中不合适,尽管在语法上它会起作用:
class Person2 {
private String fName;
public Person2(string fName) {
setFname(fName);
}
private void setFname(String fName) {
this.fName = fName.ToLower();
}
public String getFname() {
return this.fName+ ".addedText";
}
}

