2015-08-10 21 views
19

C# 6.0 giới thiệu khả năng xác định được chỉ thuộc tính:tài sản với setter tin so với get-chỉ-tài sản

public ICommand AddCommand { get; } 

Bây giờ khi xác định các bất động sản khác như sau, ReSharper gợi ý Auto-tài sản có thể được thực hiện get-chỉ:

private List<Screenshot> Screenshots { get; set; } 

Hơn nữa, ReSharper không nói một điều khi xác định thu khí tin:

public ICommand AddCommand { get; private set; } 

Sự khác biệt giữa tài sản chỉ công khai (chẳng hạn như AddCommand) đầu tiên, tài sản chỉ nhận riêng (chẳng hạn như tài sản Screenshots) và tài sản công khai riêng (chẳng hạn như AddCommand)?

Ứng dụng WPF của tôi dường như không quan tâm liệu thuộc tính công khai của nó (UICommand) có chứa một trình thiết lập riêng hoặc không có thiết lập nào cả, nhưng chắc chắn phải có sự khác biệt?

+1

Thuộc tính chỉ có giống như các trường 'readonly', chúng có thể được thiết lập trong việc xây dựng/khởi tạo đối tượng nhưng không phải sau này. Thiết lập riêng tư không đảm bảo rằng các phương thức khác không thể sửa đổi giá trị của nó sau khi xây dựng. –

+1

Tính năng "mới" trong thuộc tính đầu tiên của bạn ('AddCommand') là gì? – Amit

+1

@Amit: Bộ truy cập 'set' bị thiếu. – SeToY

Trả lời

9

Trong trường hợp cụ thể này của các lệnh ràng buộc, nó không thực sự quan trọng.

Trong các trường hợp khác, tức là có một lớp nhận dịch vụ được tiêm qua hàm tạo và bạn muốn hiển thị nó (vì bất kỳ lý do gì), điều quan trọng là sử dụng thuộc tính chỉ đọc.

Ví dụ:

public class MainViewModel 
{ 
    public INavigationService NavigationService { get; } 

    public MainViewModel(INavigationService navigationService) 
    { 
     if(navigationService == null) 
      throw new ArgumentNullException(navigationServie); 

     NavigationService = navigationService; 
    } 
} 

Khi sử dụng này, bạn đảm bảo lớp này bất biến và nó được đảm bảo rằng NavigationService sẽ không bao giờ null, do đó bạn không cần phải làm kiểm tra rỗng chống NavigationService trước khi sử dụng nó. Một khi nó rời khỏi hàm tạo, nó không bao giờ có thể được thay đổi (tốt, ngoại trừ thông qua sự phản chiếu).

Ở phía bên kia nếu bạn có

public class MainViewModel 
{ 
    public INavigationService NavigationService { get; private set; } 

    public MainViewModel(INavigationService navigationService) 
    { 
     if(navigationService == null) 
      throw new ArgumentNullException(navigationServie); 

     NavigationService = navigationService; 
    } 
} 

sau đó nó có thể viết mã (do nhầm lẫn hoặc bởi một nhà phát triển chưa từng trải) mà hiện NavigationService = null và sau đó nếu bạn không có null-kiểm tra và truy cập nó , bạn sẽ nhận được NullReferenceException và nếu không xử lý sự cố ứng dụng của bạn.

Quay lại ví dụ: Trong trường hợp ICommand ... bạn thường không truy cập Lệnh trong ViewModel, chỉ gán lệnh đó (thường là trong hàm tạo hoặc khi nội dung của mô hình chế độ xem thay đổi, như chế độ xem con đã thay đổi và bạn muốn gán lệnh của nó cho thuộc tính lệnh viewmodel cha mẹ).

Trong trường hợp của một danh sách:

Nếu bạn không bao giờ làm Screenshots = new List<ScreenShot>() hoặc Screenshots = DisplayScreenshots() trong mã của bạn và chỉ khởi tạo nó trong các nhà xây dựng, sau đó nó thực sự tốt hơn để làm cho nó chỉ đọc với cùng lý do: Sau đó, bạn có thể đảm bảo rằng Screenshots không bao giờ là vô bạn sẽ không cần phải viết mã như

if(Screenshots != null) 
{ 
    Screenshots.Add(new Screenshot(...)); 
} 

hoặc

if(Screenshot == null) 
{ 
    Screenshots = new List<Screenshot>(); 
} 

Screenshots.Add(new Screenshot(...)); 

một lần nữa và thay vào đó luôn luôn sử dụng

Screenshots.Add(new Screenshot(...)); 

này có một lợi thế rất lớn mà bạn cần ít mã, mã của bạn là dễ đọc hơn và dễ bảo trì hơn, vì bạn không thể "quên" một null-kiểm tra và có nguy cơ một NullReferenceException.

Hy vọng đã xóa nó.

19

Câu trả lời ngắn:

public ICommand AddCommand { get; } 

sẽ được hậu thuẫn bởi một trường readonly và không có mã C# sẽ có thể thay đổi nó ngoài việc thực hiện các nhà thầu.

Ngoài ra, trình biên dịch sẽ tạo mã để gán trực tiếp bản sao lưu được gửi, vì không có trình truy cập thuộc tính.

Mặt khác:

public ICommand AddCommand { get; private set; } 

sẽ được hỗ trợ bởi một readonly lĩnh vực phi và có thể được gán bất cứ lúc nào bởi bất kỳ mã với quyền truy cập vào các thành viên tư nhân.

Trong trường hợp này, trình biên dịch sẽ tạo mã cài đặt thuộc tính bình thường.

Đối với thế giới bên ngoài, người đặt riêng tư dường như không tồn tại. Vì vậy, nó giống như thể nó không thực sự tồn tại.

5

Đây là những gì thuộc tính của bạn trở nên sau khi biên dịch đã làm bài tập về nhà cho bạn:


1.public ICommand AddCommand { get; }:

private readonly ICommand <AddCommand>k__BackingField; 
public ICommand AddCommand { 
    get { return this.<AddCommand>k__BackingField; } 
} 


2.private List<Screenshot> Screenshots { get; set; }:

private List<Screenshot> <Screenshots>k__BackingField; 
private List<Screenshot> Screenshots { 
    get { return this.<Screenshots>k__BackingField; } 
    set { this.<Screenshots>k__BackingField = value; } 
} 


3.public ICommand AddCommand { get; private set; }:

private ICommand <AddCommand>k__BackingField; 
public ICommand AddCommand { 
    get { return this.<AddCommand>k__BackingField; } 
    private set { this.<AddCommand>k__BackingField = value; } 
} 

Nói tóm lại, get-chỉ công cộng tài sản có thể được gán chỉ trong constructor (vì lĩnh vực này là read-only) hoặc bằng cú pháp mới này:

public ICommand AddCommand { get; } = new MyCommand(); 

nhưng như đối với bất kỳ trường chỉ đọc nào khác, mã này vẫn được đưa vào hàm tạo, do đó không có sự khác biệt lớn:

public MyClass1() 
{ 
    this.<AddCommand>k__BackingField = new MyCommand(); 
} 
Các vấn đề liên quan