2009-04-26 43 views
7

có cách nào để tham chiếu một cá thể đối tượng được tạo bằng câu lệnh "with" không?Ví dụ đối tượng tham chiếu được tạo bằng cách sử dụng "with" trong Delphi

Ví dụ:

with TAnObject.Create do 
begin 
    DoSomething(instance); 
end; 

đâu DoSomething sẽ sử dụng tài liệu tham khảo ví dụ như khi bạn đang đi qua một thể hiện từ một biến khai báo tham chiếu đến các đối tượng được tạo ra.

Ví dụ:

AnObject := TAnObject.Create; 

Cảm ơn.

Trả lời

12

Bạn không bao giờ nên sử dụng with do thay đổi trong tương lai có thể giới thiệu nhiều hơn về phạm vi đó so với bạn dự định.

Cầm lấy cái này ví dụ:

procedure Test; 
var 
    x: Integer; 
begin 
    with TSomeObject.Create do 
    begin 
     DoSomethingWithX(x); 
     Free; 
    end; 
end; 

và sau đó sau này bạn gài trên một tài sản X trên lớp TSomeObject. Bây giờ, bạn nghĩ nó sẽ sử dụng cái gì? Biến cục bộ hoặc thuộc tính X của đối tượng?

Giải pháp tốt nhất là luôn tạo một biến cục bộ có tên ngắn và đặt bí danh đối tượng cho biến đó.

procedure Test; 
var 
    x: Integer; 
    o: TSomeObject; 
begin 
    o := TSomeObject.Create; 
    o.DoSomethingWithX(x); 
    o.Free; 
end; 
+4

xem thêm http://stackoverflow.com/questions/71419/whats -rong-với-delphis-với –

+0

Ok, tôi sẽ cắn :-) 'với' có thể gây nhầm lẫn lớn nếu bạn không cẩn thận, nhưng có những tình huống mà nó chỉ làm cho mã dễ đọc hơn nhiều. Việc đặt tên cẩn thận có thể là một số trợ giúp tại đây. Sử dụng lược đồ đặt tên để tránh nhầm lẫn là một kỹ thuật phổ biến cho mã Delphi anyway (sử dụng TXxx cho các loại, FXxxx cho các thành viên cá nhân, GetXxx và SetXxx cho getters và setters, vv). Chỉ cần sử dụng MyXxx hoặc một cái gì đó tương tự cho các biến địa phương và bạn sẽ không có nhiều sự nhầm lẫn như bạn sẽ có bằng cách gọi biến "x" và "o". –

+1

Tôi sẽ không giao dịch vài trường hợp mà nó * có thể * làm cho nó dễ đọc hơn đối với những dịp mà tôi đã từng chút bởi tính năng tự động phạm vi của nó. Tôi đã lãng phí hàng tuần về các vấn đề liên quan đến vấn đề này. Không có mã nào có thể được chứng minh là có thể đọc được vì nó đáng giá nhiều thời gian để tìm ra các lỗi kỳ lạ. –

14

Vâng, bạn có thể sử dụng cách tiếp cận như vậy:

// implement: 

type 
    TSimpleMethod = procedure of object; 

function GetThis(const pr: TSimpleMethod): TObject; 
begin 
    Result := TMethod(pr).Data; 
end; 

// usage: 

    with TStringList.Create do 
    try 
    CommaText := '1,2,3,4,5,6,7,8,9,0'; 
    ShowText(TStringList(GetThis(Free))); 
    finally 
    Free; 
    end; 

hoặc lớp người giúp đỡ:

type 
    TObjectHelper = class helper For TObject 
    private 
    function GetThis: TObject; Inline; 
    public 
    property This: TObject read GetThis; 
    end; 

... 

function TObjectHelper.GetThis: TObject; 
begin 
    Result := Self; 
end; 

Nhưng, trên thực tế, trả lời trước đó là chính xác: bạn nên quên hơn về "với" tuyên bố.

+1

+1 :) Không có công cụ trợ giúp nào tồn tại theo cách này khi tôi đang làm Delphi. – cgp

+5

+1 cho việc sử dụng điên cuồng của Delphi :)) Tuyệt vời! – gabr

+0

Cảm ơn: D – Alex

1

Tôi đã học được cách cứng - chỉ sử dụng 'Với' trong các tình huống sau:

With TMyForm.Create(Owner) do 
    try 
    ShowModal 
    finally 
    Free; 
    end; 


procedure Notify(Sender : TObject); 
begin 
    With Sender as TSomething do 
    VerySimpleProperty := Something  
end; 

tức là giữ cho tầm nhìn của Với như đơn giản càng tốt. Khi bạn đưa vào tài khoản thực tế là trình gỡ lỗi không thể giải quyết 'Với', nó thực sự tốt hơn và rõ ràng hơn để sử dụng biến cục bộ đơn giản hoặc để khai báo đầy đủ mục tiêu tức là MyRecord.Something

3

Bạn đã tự trả lời: khai báo biến cục bộ . Nếu bạn muốn, bạn có thể sử dụng với từ khóa trên đó.

var 
    MyInstance: TMyObject; 
begin 
    MyInstance := TMyObject.Create; 
    with MyInstance do 
    try 
    Foo; 
    Bar; 
    DoSomething(MyInstance); 
    finally 
    Free; 
    end; 
end; 

Trong ví dụ trên lý do duy nhất để sử dụng với là mã dễ đọc, mà là rất chủ quan, bạn cũng có thể mương với từ khóa và sử dụng MyInstance trực tiếp. Nó chỉ là vấn đề sở thích cá nhân. Tôi không đồng ý về câu trả lời "không bao giờ sử dụng với", nhưng bạn nên biết về những hạn chế của nó.

cũng Xem câu hỏi này: Is delphi "with" keyword a bad practice?

2

Một sự thêm vào ví dụ của Brian vào một handler Thông báo cho là sử dụng một biến tuyệt đối (chỉ win32):

procedure Notify(Sender : TObject); 
var 
    Something : TSomeThing absolute Sender; 
begin 
    if Sender is TSomething then 
    begin 
    VerySimpleProperty := Something.Something; 
    OtherProperty := Something.SomethingElse; 
    end; 
end; 

Về cơ bản nó tránh được việc phải gán một biến địa phương hoặc có rất nhiều loại phôi.

+0

+1 để tham gia với chúng tôi về việc sử dụng 'tuyệt đối' (mà từ lâu đã được giới thiệu cho tham chiếu bộ nhớ tuyệt đối, nhưng ví dụ của bạn là cách sử dụng duy nhất tương thích với cả .net và thế giới bản địa). –

+0

Tôi sử dụng cấu trúc này rất nhiều, nhưng gần đây đã được thực hiện nhận thức rằng nó messes với tối ưu hóa của trình biên dịch.Do đó, việc sử dụng loại cấu trúc này có thể dẫn đến việc tạo mã không hiệu quả, trong trường hợp điều này quan trọng (nhưng có thể dẫn đến mã dễ đọc hơn, IMO, trong trường hợp tốc độ không quan trọng). – HeartWare

1

này là không thể, nhưng chúng ta có thể làm cho nó trở thành hiện thực bằng cách thuyết phục những người sáng tạo biên dịch:

With TForm1.Create (Nil) Do // New TForm1 instance 
    Try 
     LogForm ("); // That same instance as parameter to an outer method (solution) 
     "ShowModal; // Instance.ShowModal 
    Finally 
     "Free; // Instance.Free 
    End; 

đề nghị của tôi là:

  1. Không nhiều hơn một đối tượng/hồ sơ cho mỗi Với tiêu đề .
  2. Không được phép Nested Withs.
  3. Sử dụng "để chỉ ra đối tượng/hồ sơ (dấu ngoặc kép tương tự như đến vạch ditto: http://en.wikipedia.org/wiki/Ditto_mark)..
0

Có một hack làm việc tốt để làm như vậy Xác định chức năng workaround này somwhere trong dự án đơn vị.

// use variable inside 'with ... do' 
// WSelf function returns TObject associated with its method. 
// I would recommend to use the method 'Free' 
// WSelf(Free) as <TObjectN> 
type TObjectMethod = procedure of object; 
function WSelf(const MethodPointer: TObjectMethod): TObject; 
begin 
    Result := TMethod(MethodPointer).Data; 
end; 

dụ sử dụng.

var 
    SL: TStringList; 
begin 
    SL := TStringList.Create; 
    try 
     with TStringList.Create do 
     try 
      Add('1'); 
      Add('2'); 
      Add('3'); 
      // (WSelf(Free) as TStringList) references to the object 
      // created by TStringList.Create 
      SL.Assign(WSelf(Free) as TStringList); 
     finally 
      Free; 
     end; 
    finally 
     ShowMessage(SL.Text); 
     SL.Free; 
    end; 
end; 
Các vấn đề liên quan