2010-11-13 34 views
7

Trong Visual Basic, nếu bạn đang đi để thay đổi nhiều thuộc tính của một đối tượng duy nhất, có một tuyên bố With/End With:C# tương đương với từ khóa Visual Basic: 'With' ... 'End With'?

Dim myObject as Object 

// ' Rather than writing: 
myObject.property1 = something 
myObject.property2 = something2 

// ' You can write: 

with myObject 
    .property1 = something 
    .property2 = something2 
    ... 
End With 

Tôi biết C# có thể làm điều đó khi tạo một đối tượng mới:

Object myObject = new Object { property1 = something, property2 = something2, ...}; 

Nhưng làm thế nào để làm điều đó nếu myOject đã được tạo ra (giống như những gì Visual Basic đang làm)?

+0

Một vài người đang nói đó là xấu, nhưng tôi muốn chỉ ra rằng công ước mã hóa của Microsoft cho VB.NET nói rằng bạn nên sử dụng từ khóa 'With' khi thực hiện một loạt các cuộc gọi đến một đối tượng - http://msdn.microsoft.com/en-us/library/h63fsef3.aspx –

Trả lời

11

Bạn không thể thực hiện việc này trong C#.

Tính năng này dành riêng cho VB và gần nhất bạn có thể đến trong C# là trình khởi tạo đối tượng như bạn mô tả.

3

Nếu bạn đang cố gắng để tránh nhiều cách gõ bạn có thể cho đối tượng của bạn một tên ngắn hơn:

var x = myObject; 
x.property1 = something; 
x.property2 = something2; 
+0

Vâng, và để thực hiện nó một bước xa hơn bạn thậm chí có thể làm 'sử dụng (var x = myObject) {/*newline*/x.property1=something;}' – Alxandr

+3

@Alxandr: Ý tưởng rất xấu, sẽ gọi là 'Vứt bỏ' ở cuối khối (và sẽ không thậm chí biên dịch cho các loại không triển khai 'IDispos có thể'). –

+0

Oo. Điểm tốt. Lỗi của tôi. Tôi chỉ nghĩ rằng nó xử lý của biến "x", nhưng mà beeing một tài liệu tham khảo có thể gây tử vong: -P – Alxandr

7

Làm thế nào về điều này?

static class Extension 
{ 
    public static void With<T>(this T obj, Action<T> a) 
    { 
     a(obj); 
    }  
} 

class Program 
{ 
    class Obj 
    { 
     public int Prop1 { get; set; } 
     public int Prop2 { get; set; } 
     public int Prop3 { get; set; } 
     public int Prop4 { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     var detailedName = new Obj(); 
     detailedName.With(o => { 
      o.Prop1 = 1; 
      o.Prop2 = 2; 
      o.Prop3 = 3; 
      o.Prop4 = 4; 
     }); 
    } 
} 
+0

Làm cho đó là một phương pháp mở rộng! Sau đó, bạn có thể làm như 'detailedName.With (o => {o.Prop1 = 4})' – Alxandr

+2

Và btw. +1 cho sự sáng tạo :-) – Alxandr

+0

@Alxandr - Ý tưởng hay. – ChaosPandion

3

Tại sao không C# có VB.NET của 'với' nhà khai thác?

Nhiều người, kể cả các nhà thiết kế ngôn ngữ C#, tin rằng 'có' thường dễ bị tổn hại, và có nhiều lời nguyền hơn là một phước lành. Rõ ràng hơn là khai báo một biến cục bộ với một tên có ý nghĩa và sử dụng biến đó để thực hiện nhiều phép toán trên một đối tượng duy nhất, hơn là có một khối với một loại ngữ cảnh ngầm định.

bởi @Jon Skeet

+6

... Và những người khác tin rằng tuyên bố "với" của VB là một tính năng hữu ích cung cấp một số ngữ nghĩa không được thuận tiện đạt được thông qua các phương tiện khác. – supercat

1

VB.NET bao gồm một số lỗi trong thiết kế VB6 của vì lợi ích của tính tương thích ngược. Trong khi Javascript có lỗ hổng thiết kế giống nhau (thực ra thậm chí còn tồi tệ hơn, vì with dẫn đến các cấu trúc không rõ ràng hơn), hầu hết các ngôn ngữ C-cú pháp khác không, vì vậy không có lợi ích tương thích ngược trong việc thêm nó vào C#.

+0

Trên thực tế, có một lợi thế khác biệt khi có 'với' trong JavaScript. Nó cho phép bạn giới thiệu một phạm vi mới cho các chức năng của bạn! – ChaosPandion

+1

Câu lệnh "With" trong VB, khi được sử dụng với cấu trúc, cung cấp ngữ nghĩa không thuận tiện trong C. Cho rằng "With" của VB sử dụng thời gian hàng đầu để tránh sự mơ hồ, tôi không chắc tại sao bạn coi nó là thiết kế lỗ hổng? – supercat

0

Nếu biểu thức "có" là loại lớp, câu lệnh "Có" tương đương với việc tạo biến tạm thời mới của loại đó, được khởi tạo thành biểu thức "Có" và đứng trước mỗi "hàng đầu". với biến đó. Tuy nhiên, nếu nó là một kiểu cấu trúc, mọi thứ phức tạp hơn. Hãy xem xét mã (rõ ràng không phải là cách một thường sẽ viết một cái gì đó, nhưng viết như nó là làm cho một điểm:.

 
    With MyPoints(N) ' Array of Point 
    N=SomeNewValue 
    .X = MyPoints(N).X 
    .Y = MyPoints(N).Y 
    End With 

Các "Với" tuyên bố một cách hiệu quả chốt một tham chiếu đến MyPoints (N) Thậm chí nếu MyPoints là thay đổi thành một số mảng khác, hoặc N được thay đổi, tham chiếu chốt sẽ vẫn trỏ đến cùng một phần tử của cùng một mảng giống như khi câu lệnh With được thực hiện.Nếu một khai báo biến cục bộ P của kiểu Point và lấy MyPoints (N), và sau đó ghi vào PX và PY, ghi sẽ chỉ nhấn vào bản sao cục bộ P, thay vì cập nhật mảng. Để đạt được ngữ nghĩa tương tự trong C#, người ta phải sử dụng các biến cục bộ để giữ cả MyPoints và N, hoặc đặt nội dung của câu lệnh With trong một hàm ẩn danh có tham số ref kiểu Point. Để tránh phải tạo một đóng cửa tại thời gian chạy, hàm ẩn danh cũng nên chấp nhận, có thể là do tham chiếu, bất kỳ biến cục bộ nào mà nó sẽ cần từ phạm vi bên ngoài.

0

@Mark Byers answer là tốt nhưng biến x sẽ hoạt động sau khi thuộc tính được đặt. Và bạn không thể sử dụng lại tên x (trong cùng một khối).

Hãy thử điều này (Và đối tượng phải có loại tài liệu tham khảo trong mẫu này):

void Main() 
{ 
    var myObject1 = new Foo(); 
    var myObject2 = new Hoo(); 

    //elided... 

    { 
     var _ = myObject1; 
     _.MyPropertyA = 2; 
     _.MyPropertyB = "3"; 
    } 

    { 
     var _ = myObject2; 
     _.MyPropertyX = 5; 
     _.MyPropertyY = "asd"; 
    } 
}