2010-10-15 26 views
6

Đối với các hardcore C lập trình # ở đây, điều này có vẻ như một câu hỏi hoàn toàn ngu ngốc - Tuy nhiên, tôi chỉ đi qua một đoạn mã mẫu trong diễn đàn AWS SDK và được hoàn toàn sideswiped bởi nó:C# cú pháp đường - cách mới để thiết lập các thuộc tính đối tượng?

RunInstancesRequest runInstance = new RunInstancesRequest() 
    .WithMinCount(1) 
    .WithMaxCount(1) 
    .WithImageId(GetXMLElement("ami")) 
    .WithInstanceType("t1.micro"); 

Đây là rất gợi nhớ cú pháp cũ của VB6 With ... End With, mà tôi đã than phiền về sự vắng mặt của C# - Tôi đã biên soạn nó trong dự án VS2008 của tôi và nó hoạt động một cách xử lý, tiết kiệm rất nhiều dòng riêng biệt tham chiếu các thuộc tính này. Tôi chắc chắn rằng tôi đã đọc các bài báo trong quá khứ giải thích tại sao VB6 kiểu With không có trong C#, vì vậy câu hỏi của tôi là: có cú pháp này luôn luôn tồn tại trong ngôn ngữ, hoặc là nó một thay đổi .NET gần đây đã kích hoạt nó? Chúng ta có thể phủ tất cả các sự kiện đối tượng theo sau bởi các thay đổi thuộc tính trong cùng một đường không?

+2

Vâng chắc chắn, bạn có thể thực hiện tất cả những phương pháp đó nếu bạn muốn. Nhưng tại sao không chỉ sử dụng cú pháp khởi tạo đối tượng? –

+1

Câu trả lời tuyệt vời ở đây, nhưng tôi chỉ có thể chấp nhận một câu trả lời - vì vậy bây giờ, đó là câu nói cụ thể liên quan đến * Giao tiếp thông thạo *, vì ví dụ trong bài viết làm cho nó rất rõ ràng những gì đang diễn ra. Tôi cảm thấy hơi xấu hổ vì tôi không tự tạo liên kết trực quan, phát hiện ra rằng toàn bộ dòng có dạng 'A.B.C.D;', nhưng tôi chưa từng thấy kỹ thuật này trước đây. Một sợi dây khác vào cung! :) –

Trả lời

16

Họ thực hiện tất cả các phương pháp đó, mỗi trong số đó cũng sẽ được trả lại đối tượng RunInstancesRequest (aka, this). Nó được gọi là Fluent Interface

+0

Liên kết đẹp. Tôi thích ví dụ này: http://en.wikipedia.org/wiki/Fluent_interface#C.23 –

4

Nó không phải là cú pháp. Những phương thức đó chỉ thiết lập thuộc tính và trả về đối tượng this.

0

Cú pháp này luôn luôn tồn tại

25

Điều này có tốt hơn không?

RunInstancesRequest runInstance = new RunInstancesRequest 
{ 
    MinCount = 1, 
    MaxCount = 1, 
    ImageId = GetXMLEleemnt("ami"), 
    InstanceType = "t1.micro" 
}; 
+1

+1 Tôi thích học những điều mới. – Brad

+0

Tôi đồng ý, để thiết lập thuộc tính/nhà xây dựng, đây là một cú pháp tốt hơn. Nhưng trong các tình huống mà bạn đang làm việc với một mục hiện có và thường sẽ sửa đổi một số thuộc tính hoặc gọi một số phương thức trong một chuỗi, giao diện thông thạo sẽ tỏa sáng. Đó là một trong nhiều lý do jQuery rất tuyệt vời khi làm việc cùng. – CaffGeek

+1

Và bạn không thể sử dụng nó trên một vật thể bất biến. Cá nhân tôi nghĩ cú pháp này chỉ nên được sử dụng nếu đối tượng gốc không bị sửa đổi (như trong LINQ). – CodesInChaos

1

Lý do cú pháp này hoạt động cho RunInstancesRequest là mỗi phương thức đều gọi bạn đang trả lại phiên bản gốc. Cùng một khái niệm có thể được áp dụng cho StringBuilder vì cùng một lý do, nhưng không phải tất cả các lớp đều có các phương thức được thực hiện theo cách này.

3

Tôi nghĩ kỹ thuật này khác với cú pháp Với ... trong VB. Tôi nghĩ đây là một ví dụ về chuỗi. Mỗi phương thức trả về một cá thể của chính nó để bạn có thể thực hiện các cuộc gọi phương thức.

Xem Method-Chaining in C#

+0

+1 Các câu trả lời xếp hạng cao hơn không đề cập đến chuỗi. –

1

Tôi muốn có một constructor mà mất tất cả những giá trị tài sản như các đối số và đặt chúng trong lớp.

+0

+1. Tôi không thích bất cứ điều gì cho phép các lớp học được xây dựng một phần sống. Tôi chỉ cần đặt lên với nó cho LINQ2SQL hoặc ORMs khác như là một artefact của trở kháng OO-ORM, nhưng không có biện minh hầu hết thời gian. Không có nghĩa là nó không thể được sử dụng bên cạnh các nhà xây dựng thích hợp và bất biến lớp học, nhưng tôi có thể thấy làm thế nào điều này sẽ khuyến khích phá vỡ từ đó. –

4
RunInstancesRequest runInstance = new RunInstancesRequest() 
.WithMinCount(1) 
.WithMaxCount(1) 
.WithImageId(GetXMLElement("ami")) 
.WithInstanceType("t1.micro"); 

==

RunInstancesRequest runInstance = new RunInstancesRequest().WithMinCount(1).WithMaxCount(1).WithImageId(GetXMLElement("ami")).WithInstanceType("t1.micro"); 

Tôi không biết nếu điều đó được coi là cú pháp đường, hoặc chỉ định dạng tinh khiết.

+0

+1: khoảng trống xung quanh '.' là (và luôn luôn bị) bỏ qua hoàn toàn bởi trình biên dịch. –

1

Nó luôn tồn tại trong C# và thực sự trong bất kỳ ngôn ngữ C-style oo (eh, phổ biến nhất ngôn ngữ C-style trừ C chính nó!)

Đó là không công bằng để so sánh nó với cú pháp VB6 With...End With, vì nó là nhiều rõ ràng hơn những gì đang xảy ra trong trường hợp này (về điều tốt duy nhất tôi phải nói về VB232 của With...End With ít nhất nó không phải là xấu như Javascripts vì nó đòi hỏi các dấu chấm trước).

Giống như mọi người đã nói, một sự kết hợp của giao diện "thông thạo" và thực tế là toán tử . cho phép khoảng trắng trước và sau nó, vì vậy chúng tôi có thể đặt từng mục trên dòng mới.

StringBuilder là trường hợp thường thấy nhất trong C#, như trong:

new StringBuilder("This") 
    .Append(' ') 
    .Append("will") 
    .Append(' ') 
    .Append("work") 
    .Append('.'); 

Một liên quan, nhưng không hoàn toàn giống nhau, mô hình là nơi bạn chuỗi các phương pháp của một đối tượng bất biến mà trả về một đối tượng khác nhau cùng loại như trong:

DateTime yearAndADay = DateTime.UtcNow.AddYears(1).AddDays(1); 

Tuy nhiên, một là trở về sửa đổi IEnumerable<T>IQueryable<T> các đối tượng từ các phương pháp liên quan LINQ.

Điều này mặc dù khác nhau về trả lại các đối tượng khác nhau, thay vì sửa đổi đối tượng có thể thay đổi và trả về cùng một đối tượng đó.

Một trong những lý do chính khiến nó phổ biến hơn trong C++ và Java so với C# là C# có các thuộc tính. Điều này làm cho các phương tiện thành ngữ nhất của việc gán các thuộc tính khác nhau một cuộc gọi đến trình thiết lập có liên quan giống như thiết lập một trường. Tuy nhiên nó chặn nhiều việc sử dụng phổ biến nhất của thành ngữ giao diện thông thạo.

Cá nhân, kể từ khi giao diện thành ngữ thông thạo không được bảo đảm (không có gì để nói MyClass.setProp(32) nên trở this hoặc thực sự, rằng nó không nên trở 32 mà cũng sẽ có ích trong một số trường hợp là), và vì nó không phải là thành ngữ trong C#, tôi thích để tránh nó ngoài với StringBuilder, mà là một ví dụ nổi biết như vậy mà nó gần như tồn tại như một StringBuilder thành ngữ riêng biệt trong C#

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