[英]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.