[英]The C# Shorthand getters and setters
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());
}
}
在C#中使用速记
public class Person {
public string fName{ get; set;}
}
C#速记getter和setter如何在此上实现封装? 如何实现与上述Java代码相同的C#代码? 有什么限制吗? 根据我的观察,我只能将“ fName”设置为public才能使用,特别是“ public string fName {get; set;}”,但是在私有方面我不能使用。 但是当我将其设置为私有时,我将无法再通过其他方法访问它。
它们不允许您指定封装行为。 它们的作用是允许您在班级的公共界面(而不是字段)中指定这是一个Property。
此处的区别在于,在Java中,getter和setter只是遵循某种约定(getXXX,setXXX)的方法。 在C#中,属性是一流的构造(即使它们基本上是幕后的获取器和设置器)。 因此,C#提供了这些方法,以一种简短的方式表示您稍后可以实现封装(例如,将行为添加到getter或setter中),但是您不想破坏类的使用者,因此您将它们声明为属性。
在Java中:
public class Foo {
private String fooName;
public String BarName;
public String getFooName() { return fooName; }
public String setFooName(String fooName) { this.fooName = fooName; }
}
在C#中:
public class Foo {
public String FooName { get; set; }
public String BarName;
}
假设您在另一个引用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;
}
}
现在,将Foo更改为此不会破坏FooReader:
public class Foo {
private String _fooName;
public String FooName { get { return _fooName.ToUpper(); } set { _fooName = value; } }
public String BarName;
}
但是将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; } }
}
就像您自己说的那样,C#版本是以下各项的简写:
private string _name;
public Name
{
get { return _name; }
set { _name = value; }
}
(请注意,私有字段不可访问,它是由编译器生成的。所有访问都将通过属性进行,即使是在类内部也是如此)
与java相比,getter / setter只是方法,该构造在C#中称为属性,并且是编译器功能。
在C#中,Person类中的代码等效于:
private String _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
从C#3开始,您可以将其压缩为:
public string Name { get; set; }
这是一个自动实现的属性 ,编译器将自动生成与长时间编写时相同的封装代码。 会自动为您生成一个私有后备字段以及get
和set
方法。 确实,一旦编译器生成了IL代码,您将拥有一个带有两个方法的字段,即get_Name
和set_Name
,因此,通过使用auto-implemented属性,您可以让编译器生成与您使用的几乎相同的代码。您的Java示例。
我将略微修改您的问题,以提供更好的比较。 在Java中,通常有公共的getter和private的setter,而构造函数是变量的initializor [sic],例如:
public class Person{
private String fName;
public Person (String name) {
setName(name);
}
private void setName(String someName){
fName = someName;
}
String getName(){
return fName;
}
}
对于该类的用户,只能在初始化之后通过构造函数来检索值:
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
}
现在,这是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
}
现在,如果您想使用上述约定将逻辑添加到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;
}
}
现在,这是否比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";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.