2009-12-02 28 views
10

câu hỏi của tôi là đơn giản, đang sử dụng các thuộc tính get set của C# được coi là tốt, tốt hơn thậm chí là viết phương thức getter và setter? Khi bạn sử dụng các thuộc tính này, bạn không phải khai báo thành viên dữ liệu lớp của mình là công khai? Tôi hỏi điều này bởi vì giáo sư của tôi nói rằng các thành viên dữ liệu nên không bao giờ được khai báo là công khai, vì nó được coi là thực hành không tốt.Việc sử dụng các thuộc tính được thiết lập của C# có được coi là thực hành tốt không?

này ....

class GetSetExample 
{ 
    public int someInt { get; set; } 
} 

vs này ...

class NonGetSetExample 
{ 
    private int someInt; 
} 

Edit:

Nhờ tất cả các bạn! Tất cả các câu trả lời của bạn đã giúp tôi và tôi đã bỏ phiếu thích hợp cho câu trả lời của bạn.

+0

đây thực sự là điều chúng tôi yêu cầu khi chúng tôi phỏng vấn các ứng dụng mới. Tại sao bạn sẽ sử dụng lần đầu tiên trong lần thứ hai :-) –

+0

Các giáo sư phải đủ thông minh để biết không sử dụng tuyệt đối! Trừ khi anh ta định nghĩa lại "không bao giờ" có nghĩa là "không phải không có sự hiểu biết và chấp nhận những hậu quả có thể" ... –

Trả lời

14

này:

class GetSetExample 
{ 
    public int someInt { get; set; } 
} 

là thực sự giống như thế này:

class GetSetExample 
{ 
    private int _someInt; 
    public int someInt { 
     get { return _someInt; } 
     set { _someInt = value; } 
    } 
} 

Cú pháp get; set; chỉ là một cách viết tắt thuận tiện cho việc này mà bạn có thể sử dụng khi phương thức getter và setter không làm bất cứ điều gì đặc biệt.

Vì vậy, bạn không để lộ một thành viên công khai, bạn đang xác định một thành viên riêng và cung cấp các phương thức get/set để truy cập nó.

4

Trong ví dụ đầu tiên của bạn, C# sẽ tự động tạo các trường sao lưu riêng tư, vì vậy về mặt kỹ thuật, thành viên dữ liệu không được khai báo là chỉ công khai getter/setter.

+0

Về mặt kỹ thuật, nhưng nó hoàn toàn là một sự phân biệt vô nghĩa. –

+8

Không thực sự. Các thuộc tính có thể được sử dụng trong các khu vực khác trong khi các phương thức hoặc các trường không thể. Tự động ràng buộc xuất hiện trong đầu bạn. –

+7

Nó thực sự là khá quan trọng trong một số tình huống. Nếu bạn khai báo một biến công khai thì bạn bị mắc kẹt với nó là một biến public trừ khi bạn muốn thay đổi ABI thành assembly đó.Với một {get; bộ; } tài sản công cộng, tất cả các truy cập công cộng đang xảy ra thông qua các phương thức accessor, do đó bạn có thể thay đổi các phương thức accessor để có chức năng khác sau này mà không buộc mọi người phải biên dịch lại các ứng dụng tham chiếu đến assembly của bạn. –

0

Khá hợp lý và giáo sư của bạn (không có ngữ cảnh) là sai. Nhưng dù sao, bằng cách sử dụng "tính chất tự động", là tốt, và bạn có thể làm điều đó cho dù họ là công cộng hay tư nhân.

Mặc dù trong kinh nghiệm của tôi, bất cứ khi nào tôi sử dụng, tôi gần như chắc chắn sẽ cần phải viết một số logic trong đó, và do đó không thể sử dụng các đạo cụ tự động.

+1

Tôi đoán ngữ cảnh sẽ là Java (hoặc có thể là C++), vì Java không có các thuộc tính như C#. – FrustratedWithFormsDesigner

+0

Nếu bạn có toàn quyền kiểm soát toàn bộ nguồn và nó luôn được biên dịch cùng nhau thì nó thực sự tạo ra sự khác biệt nhỏ cho dù bạn sử dụng các thuộc tính hoặc biến công cộng (ngoại trừ trong các tình huống đặc biệt). Tuy nhiên, trong những tình huống mà những người khác nhau đang viết các phần khác nhau của mã, nó trở nên quan trọng hơn. Thư viện chuyên nghiệp không hiển thị các biến công khai cho mã bên ngoài. –

+0

Đọc những câu trả lời này tôi cảm thấy một chút như tôi đang ở trong khu vực hoàng hôn. –

7

Có, các thành viên thường không bao giờ được tuyên bố công khai trong thiết kế tốt vì nhiều lý do. Hãy suy nghĩ về OOP, nơi bạn kế thừa lớp sau. Loại khó để ghi đè lên một lĩnh vực. :-) Ngoài ra nó ngăn cản bạn giữ cho nội bộ của bạn không bị truy cập trực tiếp.

Nhận đơn giản; bộ; thiết kế đã được giới thiệu trong C# 2.0. Về cơ bản nó giống như tuyên bố mọi thứ với một thành viên riêng tư ủng hộ nó (dịch ngược nó ra thành công cụ như Reflector và xem).

public int someInt{get;set;} 

bằng trực tiếp đến

private int m_someInt; 
public int someInt{ 
    get { return m_someInt; } 
    set { m_someInt = value; } 
} 

Phần lớn về việc có getter đơn giản/setter là khi bạn muốn điền thông tin vào thực hiện với một chút hơn ruột sau, bạn không phá vỡ Khả năng tương thích ABI.

Đừng lo lắng về getter/setters làm chậm mã của bạn thông qua vô hướng. JIT có một thứ gọi là inlineing làm cho việc sử dụng getter/setter cũng hiệu quả như truy cập trực tiếp.

+1

Tôi đồng ý. Xem xét thư viện .NET trực tiếp dài. Để duy trì nó, bạn phải rất cẩn thận trước khi phơi bày cái gì đó với thế giới bên ngoài, và hầu hết thời gian bạn nên phơi bày một tài sản, thay vì một lĩnh vực. Đây là cách an toàn nhất như trong các phiên bản sau, bạn có thể tự do thay đổi việc triển khai thuộc tính này mà không làm tổn hại đến hội đồng gọi điện. Điều gì sẽ xảy ra nếu bạn phơi bày một trường trực tiếp? Đó phải là một cơn ác mộng vô tận vì bạn không bao giờ có thể thay đổi nó kể từ đó. –

1

Trong cách tiếp cận hướng đối tượng "thuần túy", nó không được coi là OK để hiển thị trạng thái của đối tượng của bạn, và điều này áp dụng cho các thuộc tính khi chúng được triển khai trong .NET và get_ set_ properteis của Java/EJB. Ý tưởng là bằng cách phơi bày trạng thái của đối tượng của bạn, bạn đang tạo ra các phụ thuộc bên ngoài để biểu diễn dữ liệu nội bộ của đối tượng của bạn. Một thiết kế đối tượng thuần túy làm giảm tất cả các tương tác với các thông điệp với các tham số.

Trở lại với thế giới thực: nếu bạn cố gắng thực hiện một cách tiếp cận lý thuyết nghiêm ngặt về công việc, bạn sẽ bị cười ra khỏi văn phòng hoặc bị đánh vào bột giấy. Các thuộc tính rất phổ biến bởi vì chúng là một sự thỏa hiệp hợp lý giữa một thiết kế đối tượng thuần túy và dữ liệu riêng được hiển thị đầy đủ.

7

Có. Thành viên dữ liệu phải là thuộc tính riêng và tự động cho phép nó và cung cấp quyền truy cập công khai đúng cách.

Nhưng bạn nên cẩn thận. Hiểu ngữ cảnh là rất quan trọng. Trong ứng dụng luồng, cập nhật một thuộc tính sau một thuộc tính liên quan khác có thể gây hại cho tính nhất quán. Trong trường hợp đó, một phương thức setter cập nhật hai thành viên dữ liệu riêng theo cách thích hợp sẽ có ý nghĩa hơn.

0

giáo sư của bạn khá đúng.

Hãy xem xét ví dụ tầm thường này về lý do tại sao "getters" phải tránh: Có thể có 1.000 cuộc gọi đến phương thức getX() trong chương trình của bạn và mọi cuộc gọi đó giả định giá trị trả lại là một loại cụ thể. Giá trị trả lại của getX() có thể được sotred trong một biến địa phương, ví dụ, và kiểu biến phải phù hợp với kiểu trả về. Nếu bạn cần thay đổi cách đối tượng được triển khai theo cách mà loại thay đổi là X, bạn gặp rắc rối nghiêm trọng. Nếu X từng là int, nhưng hiện giờ phải là long, giờ bạn sẽ nhận được 1.000 lỗi biên dịch. Nếu bạn khắc phục sự cố không chính xác bằng cách truyền giá trị trả lại cho int, mã sẽ biên dịch gọn gàng nhưng sẽ không hoạt động. (Giá trị trả lại có thể bị cắt bớt.) Bạn phải sửa đổi mã xung quanh mỗi một trong số 1.000 cuộc gọi đó để bù đắp cho thay đổi. Tôi, ít nhất, không muốn làm nhiều việc đó.

Holub On Patterns

+0

Điều đó không thực sự có ý nghĩa gì trong ngữ cảnh của câu hỏi. Phương án thay thế là gì? Không bao giờ để ai đó truy xuất một thành viên lớp học? – Sterno

+0

Sterno: vâng, ngay cả giáo sư của ông có vẻ như vậy ("giáo sư của tôi nói rằng các thành viên dữ liệu không bao giờ nên được công khai là công khai"). tại sao nó xấu để khai báo thành viên dữ liệu công khai, nhưng viết nhiều mã hơn để * chính xác cùng một hiệu ứng * là ok? –

+0

Tôi đồng ý với những gì giáo sư của ông nói. Tôi chỉ không thực sự nghĩ rằng những gì bạn trích dẫn làm cho rất nhiều ý nghĩa trong ứng dụng thực tế. Các công cụ như Resharper làm thay đổi một loại biến khá tầm thường, và thậm chí nếu bạn không sử dụng getter/setter. phương pháp, nó không có nghĩa là bạn sẽ tránh đau liên quan với việc thay đổi một loại tài sản. Vì vậy, trong khi tôi trở lại những gì giáo sư của ông nói, tôi không nghĩ rằng báo giá này không nhiều để hỗ trợ các đối số. – Sterno

1

bởi vì với thành viên dữ liệu công cộng, mà thành viên dữ liệu có thể được thay đổi hoặc có thể được đọc ra khỏi lớp và bạn không thể kiểm soát đọc/ghi khả năng tiếp cận hoạt động nhưng với tài sản mà bạn có thể kiểm soát đọc/viết dòng ví dụ xem xét tuyên bố này:

public MyVar{private get; public set;} 

nghĩa giá trị của MyVar có thể thay đổi chỉ bên trong lớp và có thể được đọc ra khỏi lớp (đọc riêng và đọc công khai) và đây không phải là p có thể chỉ với các thành viên dữ liệu công khai

+0

Mẹo người dùng mới: Sẽ không hữu ích khi thêm câu trả lời cho câu hỏi rất cũ, khi câu hỏi đó đã có nhiều câu trả lời. – hyde

Các vấn đề liên quan