2012-01-15 14 views
6

Làm thế nào để người định cư và Getters trong C# thực hiện đóng gói? Tôi không mới khi nói đến những người định cư và getters, tôi có nền tảng với lập trình, đặc biệt là java. trong java bạn sử dụng setters và thu khí như thế nàyC# Shorthand getters và setters

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

Và trong C# Sử dụng Shorthand

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

như thế nào C# viết tắt getter và setter thực hiện đóng gói về điều này? làm cách nào để triển khai mã C# giống như mã java ở trên? có bất kỳ hạn chế nào liên quan đến nó? và dựa trên quan sát của tôi, tôi chỉ có thể sử dụng "fName" nếu nó được đặt thành công khai, cụ thể là "public string fName {get; set;}" nhưng khi nói đến riêng thì tôi không thể. nhưng khi tôi đặt nó ở chế độ riêng tư, tôi không còn có thể truy cập nó bằng các phương thức khác.

+1

Chúng được gọi là thuộc tính. Xem http://msdn.microsoft.com/en-us/library/x9fsa0sw.aspx –

Trả lời

10

Chúng không cho phép bạn chỉ định hành vi đóng gói. Những gì họ làm là cho phép bạn chỉ định rằng đây là Thuộc tính trong giao diện công khai của lớp học của bạn, trái ngược với một trường.

Sự khác biệt ở đây là trong Java, getters và setters là các phương thức đơn giản tuân theo quy ước nhất định (getXXX, setXXX). Trong C#, các thuộc tính là một cấu trúc hạng nhất (mặc dù chúng về cơ bản là getters và setters đằng sau hậu trường). Vì vậy, C# cung cấp những cách viết tắt này để nói rằng bạn có thể triển khai đóng gói sau này (ví dụ: thêm hành vi vào getter hoặc setter) nhưng bạn không muốn phá vỡ người tiêu dùng của lớp học, vì vậy bạn tuyên bố chúng là thuộc tính ở phía trước.

Trong Java:

public class Foo { 
    private String fooName; 
    public String BarName; 
    public String getFooName() { return fooName; } 
    public String setFooName(String fooName) { this.fooName = fooName; } 

} 

Trong C#:

public class Foo { 
    public String FooName { get; set; } 
    public String BarName; 
} 

Hãy giả sử bạn có một FooReader lớp người tiêu dùng quy định tại lắp ráp khác tham chiếu đến assembly Foo:

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

Bây giờ , thay đổi Foo thành số này không ngắt FooRe Ader:

public class Foo { 
    private String _fooName; 
    public String FooName { get { return _fooName.ToUpper(); } set { _fooName = value; } } 
    public String BarName; 
} 

nhưng thay đổi Foo để WILL nghỉ này FooReader- bạn sẽ cần phải biên dịch lại nó:

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; } } 
} 
+0

Tôi vẫn còn bối rối, tôi sẽ không muốn là một bận tâm nhưng bạn sẽ nhớ đăng một ví dụ về một số loại? với java và C# so sánh? – user962206

+0

@ user962206 Bạn có thể thay thế thuộc tính đơn giản sau này bằng một thuộc tính phức tạp hơn với logic tùy ý nếu bạn phải thực hiện hành vi cụ thể trong khi vẫn giữ lại khả năng tương thích mã nhị phân và mã nguồn. – Voo

+0

Xem các ví dụ ở trên –

4

Như bạn nói cho mình, phiên bản C# là một cách viết tắt sau:

private string _name; 

public Name 
{ 
    get { return _name; } 
    set { _name = value; } 
} 

(Lưu ý rằng trường riêng tư không thể truy cập được, trình biên dịch được tạo. Tất cả các truy cập của bạn sẽ được thông qua tài sản, ngay cả từ bên trong lớp)

So với java, nơi getter/setter là các phương thức đơn giản, cấu trúc này được gọi là thuộc tính trong C# và là một tính năng trình biên dịch.

+2

Ngoại trừ tên của trường sao lưu là tên do trình biên dịch tạo ra, không thể sử dụng được từ mã C#. –

+0

@BenVoigt và là chi tiết triển khai có thể thay đổi ngay cả khi bạn quản lý để tìm ra. –

+0

@ Femaref Giá trị là gì và làm cách nào để so sánh nó với mã java? –

2

Trong, C# tương đương với mã bên trong lớp Person của bạn sẽ là:

private String _name; 

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

Tính đến C# 3, bạn có thể ngưng tụ mà xuống:

public string Name { get; set; } 

Đây là một automatically implemented property và trình biên dịch sẽ tự động tạo ra cùng một mã đóng gói vì nó sẽ nếu bạn viết nó ra một đoạn đường dài. Trường sao lưu riêng tư được tạo tự động cho bạn, cũng như các phương thức getset. Thực sự, khi trình biên dịch tạo mã IL, bạn sẽ có một trường có hai phương thức, get_Nameset_Name, do đó, bằng cách sử dụng thuộc tính được tự động triển khai, bạn cho phép trình biên dịch tạo ra cùng mã giống như bạn có ví dụ java của bạn.

+0

Ohhh, nhưng làm cách nào tôi có thể thêm giá trị vào tên của mình bằng cách sử dụng "tên chuỗi công khai {get; set;}"? ví dụ tôi sẽ tạo một đối tượng của lớp đó, Person p = new Person(). thì tôi gọi những người định cư và getters như thế nào? trong java tôi có thể làm điều đó bởi p.getName, p.setName ("Bib"), nhưng trong C# làm thế nào tôi sẽ làm điều đó ?? – user962206

+0

Trong C# bạn sẽ sử dụng 'string personsName = p.Name' cho getter và' p.Name = "something" 'cho setter. –

+0

Tôi hiểu rồi. nhưng tôi có sử dụng nó không. như thế này Console.WriteLine (p.Name) ?? và câu hỏi cuối cùng, với câu trả lời của bạn có nghĩa là, Có đóng gói trên getters tay ngắn và setters của C#? – user962206

1

Tôi sẽ sửa đổi một chút câu hỏi của bạn để cung cấp so sánh tốt hơn. Trong Java bạn thường có thu khí công và setters tư nhân, với các nhà xây dựng là initializor [sic] của biến, chẳng hạn như:

public class Person{ 
    private String fName; 

    public Person (String name) { 
     setName(name); 
    } 

    private void setName(String someName){ 
     fName = someName; 
    } 

    String getName(){ 
     return fName; 
    } 
} 

Với một người sử dụng của lớp chỉ có thể để lấy giá trị sau khi khởi tạo thông qua các nhà xây dựng:

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 
} 

Bây giờ đây là nơi mà C# có thể trở nên khó hiểu, như thay vì sử dụng Person.getName bạn chỉ cần sử dụng biến bản thân, tuy nhiên biến này có thể vẫn được đóng gói. Trong Java, bạn được dạy rằng các biến Class phải là local (private) và chỉ nên được truy cập với getters và setters. C# về cơ bản là giống nhau, nhưng cú pháp và logic là khác nhau. Viết lại ví dụ của tôi trong C# sẽ là:

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 
} 

Bây giờ nếu bạn muốn thêm logic để getter và setter của bạn bằng cách sử dụng công ước trên, bạn sẽ cần phải giới thiệu một biến tin địa phương, nhưng các mã trong Example và Person của bạn nhà xây dựng sẽ không thay đổi:

class Person { 
    private String _fName; 
    public String fName { 
     get { return _fName + ".addedText"; } 
     private set { _fName = value.ToLower(); } 
    } 
    public Person(String fName) { 
     this.fName = fName; 
    } 
} 

Bây giờ cho dù đây là tốt hơn hoặc tồi tệ hơn Java có phần gây tranh cãi, nhưng từ những gì tôi đã nhìn thấy mã của bạn sẽ là không thích hợp trong C# nếu bạn làm điều gì đó như bên dưới, mặc dù cú pháp khôn ngoan nó sẽ hoạt động:

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