Đánh giá, nhận xét, review các công ty tuyển dụng
Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 18 kết quả

Đề tài: Ref và Out Trong lập trình C#

  1. #1
    Ngày gia nhập
    04 2009
    Bài viết
    24

    Wink Ref và Out Trong lập trình C#

    Chào các bạn !
    Mình mới nghiên cứu C# (chắc cũng gần 4 tháng rồi). Lang thang qua các diễn đàn C# cũng nhiều, google (đương nhiên với từ khóa là C# rồi ). Tích lũy kiến thức tuy còn rời rạc nhưng cũng xin mạnh dạn đưa ra một bài viết. Hi vọng mọi người có gì bỏ qua và góp ý cho mình nha, vì kiến thức còn chữa nhiều mà, đưa bài này lên cũng chỉ với mục đích coi mình còn thiếu sót hay sai sót chỗ nào thôi.
    Sau đây là bài tút của mình.
    Phân biệt giữa truyền tham chiếu (ref) và truyền tham chiếu với biến chưa khởi tạo (out)
    + Đầu tiên là công dụng của hai biến này đã :
    công dụng của chúng là lấy giá trị của tham chiếu truyền vào các phương thức (hàm) sau khi đã được các phương thức xử lý. Nghe có vẻ hơi mờ hồ nhỉ ! tại cũng chẳng biết diễn đạt sao nữa. Thồi thì cứ coi ví dụ rồi hẵng tính nha ^.^
    Đây là hàm :
    Visual C# Code:
    1. public void CongSo(int a,int b)
    2. {
    3.     a = a+1;
    4.     b = b+2;
    5. }

    Đây là truyền giá trị cho ham:
    Visual C# Code:
    1. int a1 = 2;
    2. int b1 = 4;
    3. CongSo(a1,b1)
    Hàm này chẳng trả về điều gì cả (nếu có trả về điều gì đó thì cũng kệ ha ^.^). Giờ ta sẽ có một vấn đề là : “ta muốn lấy giá trị của biến a và biến b sau khi ham CongSo đã thực hiển việc cộng a cho 1 và cộng b cho 2”
    câu trả lời là dùng ref hoặc out.
    + Cách dùng :
    để sử dụng ref hoặc out để lấy giá trị của tham chiếu ta dùng như sau:
    Về ham:
    Visual C# Code:
    1. public  void CongSo(ref int a, ref int b)
    2. //public void CongSo(out int a,out int b)

    Và :
    Visual C# Code:
    1. CongSo(ref a1, ref b1)
    2. //CongSo(out a1,out b1)

    Giờ ta có thể lấy giá trị của biến a1 và biến b1 một cách dễ dàng như các biến bình thường khác rồi.
    Code:
    Console.WriteLine("Gia Tri Da Su Ly : {0}:{1}:{2}",a1,b1)
    + Giờ ta sẽ đi tới những điểm khác nhau của hai thằng này: theo sách vở bảo thì out là phần mở rộng của ref những mình chẳng thấy như vậy, theo mình thì out là bổ xung thêm tính năng cho ref ở một số trường hợp nhất định (mà mình mới biết có một thôi. Hi vọng pro góp ý)
    - Giờ coi nó khác nhau ở đâu nha.
    ref có thể thực hiện các phép tính với chính những tham chiếu mà nó truyền vô trong khi out làm như vậy sẽ bị báo lỗi. Như ví dụ sau :

    Visual C# Code:
    1. public void CongSo(out int a,out int b)
    2. {
    3.     a = a+a;
    4.     b = b+a;
    5. }

    Sẽ xuất hiện lỗi
    Use of unassignes out parameter ‘a’
    Use of unassignes out parameter ‘b’
    Dịch thì mình chịu nha. Vì anh văn của mình chỉ bằng con số 0 mà thôi. Hic (biết là đã theo it thì điều đó là ko được nhưng nuốt không có nổi.)
    - giờ ta sẽ bỏ hai dòng gán giá trị cho biến a1, và b1 đi
    Visual C# Code:
    1. int a1;
    2. int b1;

    và sử dụng thằng ref thì sẽ bị báo lỗi là :
    Use of unassignes local parameter ‘a1’
    Use of unassignes local parameter ‘b1’
    Nhưng với out thì lại hoàn toàn OK. Vậy ta có thể nói là với ref thì biến truyền vào luôn phải có giá trị, trong khi với out thì không cần.
    Vậy là hết những gì mình biết về hai thằng này rồi. Có gì mọi người bổ sung thêm nha.
    À. Còn một điều nữa là ta có thể kết hợp cả hai thằng này cũng được nha.
    Ví dụ như thế này :
    Visual C# Code:
    1. CongSo(int h, out int m,ref int s)
    Còn đây là code áp dụng thằng này để mọi người vọc nha (theo code của cuốn “Ngôn Ngữ Lập Trình C#” co chỉnh lại) chạy trên Cosole nha :
    Visual C# Code:
    1. using System;
    2. public class ThoiGian
    3. {
    4.     private int Y, M, D, H, Mi, S;
    5.     public void thoigian()
    6.     {
    7.         Console.WriteLine("Thoi Gian Hien Tai : {0}/{1}/{2}/ {3}:{4}:{5}",D,M,Y,H,Mi,S);
    8.     }
    9.    
    10.     //public void GetTime(ref int h, ref int m,ref int s)
    11.     public void GhetTime(out int h,out int m,out int s)
    12.     {
    13.         h = H;//h = H + h;
    14.         m = Mi;//m = Mi + m;
    15.         s = S;// s = S + s;
    16.     }
    17.     public ThoiGian(DateTime dt)
    18.     {
    19.         Y = dt.Year;
    20.         M = dt.Month;
    21.         D = dt.Day;
    22.         H = dt.Hour;
    23.         Mi = dt.Minute;
    24.         S = dt.Second;
    25.     }
    26.  }
    27. public class ThucThi
    28. {
    29.     static void Main()
    30.     {
    31.         DateTime thoi = DateTime.Now;
    32.         ThoiGian t = new ThoiGian(thoi);
    33.         t.thoigian();
    34.         int theH = 1;//int theH;
    35.         int theM = 1;//int theM;
    36.         int theS = 1;//int theS;
    37.         //t.GetTime(ref theH,ref theM,ref theS);
    38.        t.GhetTime(out theH, out theM, out theS);
    39.         Console.WriteLine("Thoi Gian Duoc Chinh Lai : {0}:{1}:{2}",theH,theM,theS);
    40.        
    41.     }
    42. }
    Thằng Thích Thằng Chê Mặc Kệ Người Đời Soi Mói. Tao Thích Tao Làm Tao Làm, Tao Làm Những Gì Tao Thích

  2. #2
    Ngày gia nhập
    11 2008
    Bài viết
    14

    bạn sẽ không thể phân biệt được ref và out nếu chỉ dùng các kiểu giá trị trong ví dụ.
    Hãy thử với việc truyền tham chiếu với các kiểu tham chiếu như class, interface... hay đơn giản là thử với string.

  3. #3
    Ngày gia nhập
    07 2007
    Nơi ở
    TP.HCM
    Bài viết
    199

    Bài viết của bạn rất có ích, nhưng qua bài viết của bạn mình nghĩ bạn chưa hiểu rõ công dụng của ref và out.

    Từ khóa out ở đây C# muốn chỉ rằng biến đưa vào sẽ là kết quả đầu ra sau khi gọi hàm. Và hàm sẽ không quan tâm tới đầu vào nó là gì, chỉ cần biết là tính toán và trả giá tri ra biến out đó. vd void sum(int a, int b, out s). Vì thế mà C# sẽ coi nó là chưa gán giá tri và không có lý do gì để sử dụng nó để tính toán lần đầu cả (s = s + a)

    Còn từ khóa ref mở rộng hơn out, vừa là dữ liệu vào (input) và cũng vừa là kết quả ra (output). vd swap(ref int a, ref int b). Đã là dữ liệu đầu vào thì tất nhiên trước khi đưa vào nó phải có giá trị, và tất nhiên nó phải được gán trước đã.

    Ref và out nói riêng và C# nói chung còn mang tính cấu trúc ở C++.

    Use of unassignes local parameter ‘a1’: có nghĩa là bạn đã sử dụng biến chưa được gán giá trị.

    Nên có thói quen khởi tạo giá trị biến ngay lúc khai báo nhé int a = 0;, hoặc gán giá trị trong constructor. Điều này tránh lỗi khi lập trình. Mình đã bị lỗi này khi làm với C++ , chạy debug thì ok nhưng chạy release lỗi không hiểu vì sao, mất cả buổi để phát hiện. :(


    Còn đối với object (class).
    vd:
    Visual C# Code:
    1. class clsA
    2. {
    3.     private int x;
    4.     clsA(int newx) { x = newx; } // constructor
    5.     void Setx(int newx) { x = newx; } // change value x.
    6.     string ToString() { return x.ToString(); } // print clsA.
    7. }
    8.  
    9. void method0(clsA a) //tương đương [B]clsA* a[/B] bên C++
    10. {
    11.     a.Setx(19);
    12. }
    13.  
    14. void method1(clsA a) //tương đương [B]clsA* a[/B] bên C++
    15. {
    16.     clsA a2(5);
    17.     a = a2;
    18. }
    19.  
    20. void method2(ref clsA a) //tương đương [B]clsA*& a[/B] bên C++
    21. {
    22.     clsA a2(5);
    23.     a = a2;
    24. }
    25.  
    26. void main()
    27. {
    28.     clsA a1(0);
    29.     Console.WriteLine(a1); // ra 0
    30.  
    31.     method0(a1);
    32.     Console.WriteLine(a1); // ra 19
    33.  
    34.     method1(a1);
    35.     Console.WriteLine(a1); // ra 19
    36.  
    37.     method2(ref a1);
    38.     Console.WriteLine(a1); // ra 5
    39. }
    Đã được chỉnh sửa lần cuối bởi DKhanh : 09-06-2009 lúc 09:13 AM.

  4. #4
    Ngày gia nhập
    04 2009
    Bài viết
    24

    thank nhiều !
    đó là mục đích chính mà mình post bài mà. mới học nên cần tìm hiểu là chính.
    Thằng Thích Thằng Chê Mặc Kệ Người Đời Soi Mói. Tao Thích Tao Làm Tao Làm, Tao Làm Những Gì Tao Thích

  5. #5
    Ngày gia nhập
    06 2009
    Bài viết
    4

    uhm, Theo mình thì trong C# ref và out có ý nghía giống nhau ( như mấy bạn có nói qua) , Nhưng mình nghĩ điểm khác nhau cơ bản giữa ref và out là:

    Dùng ref thì biến đó bắt buộc phải đc khởi tạo, còn dùng out thì không cần.

  6. #6
    Ngày gia nhập
    08 2009
    Bài viết
    40

    Mặc định Ref và Out Trong lập trình C#

    Trích dẫn Nguyên bản được gửi bởi Ð.Khánh Xem bài viết
    Bài viết của bạn rất có ích, nhưng qua bài viết của bạn mình nghĩ bạn chưa hiểu rõ công dụng của ref và out.

    Từ khóa out ở đây C# muốn chỉ rằng biến đưa vào sẽ là kết quả đầu ra sau khi gọi hàm. Và hàm sẽ không quan tâm tới đầu vào nó là gì, chỉ cần biết là tính toán và trả giá tri ra biến out đó. vd void sum(int a, int b, out s). Vì thế mà C# sẽ coi nó là chưa gán giá tri và không có lý do gì để sử dụng nó để tính toán lần đầu cả (s = s + a)

    Còn từ khóa ref mở rộng hơn out, vừa là dữ liệu vào (input) và cũng vừa là kết quả ra (output). vd swap(ref int a, ref int b). Đã là dữ liệu đầu vào thì tất nhiên trước khi đưa vào nó phải có giá trị, và tất nhiên nó phải được gán trước đã.

    Ref và out nói riêng và C# nói chung còn mang tính cấu trúc ở C++.

    Use of unassignes local parameter ‘a1’: có nghĩa là bạn đã sử dụng biến chưa được gán giá trị.

    Nên có thói quen khởi tạo giá trị biến ngay lúc khai báo nhé int a = 0;, hoặc gán giá trị trong constructor. Điều này tránh lỗi khi lập trình. Mình đã bị lỗi này khi làm với C++ , chạy debug thì ok nhưng chạy release lỗi không hiểu vì sao, mất cả buổi để phát hiện. :(


    Còn đối với object (class).
    vd:
    Visual C# Code:
    1. class clsA
    2. {
    3.     private int x;
    4.     clsA(int newx) { x = newx; } // constructor
    5.     void Setx(int newx) { x = newx; } // change value x.
    6.     string ToString() { return x.ToString(); } // print clsA.
    7. }
    8.  
    9. void method0(clsA a) //tương đương [B]clsA* a[/B] bên C++
    10. {
    11.     a.Setx(19);
    12. }
    13.  
    14. void method1(clsA a) //tương đương [B]clsA* a[/B] bên C++
    15. {
    16.     clsA a2(5);
    17.     a = a2;
    18. }
    19.  
    20. void method2(ref clsA a) //tương đương [B]clsA*& a[/B] bên C++
    21. {
    22.     clsA a2(5);
    23.     a = a2;
    24. }
    25.  
    26. void main()
    27. {
    28.     clsA a1(0);
    29.     Console.WriteLine(a1); // ra 0
    30.  
    31.     method0(a1);
    32.     Console.WriteLine(a1); // ra 19
    33.  
    34.     method1(a1);
    35.     Console.WriteLine(a1); // ra 19
    36.  
    37.     method2(ref a1);
    38.     Console.WriteLine(a1); // ra 5
    39. }
    Đúng như bạn nói, cả ref và out đều là cách truyền tham chiếu (passed by reference) nhưng chúng khác nhau về ngữ cảnh. Giả sử khai báo 1 biến a, sau đó khởi tạo 1 gt cho biến =1 .
    Khi truyền vào 1 hàm bằng ref param, tức là hàm plusOne() đó sử dụng param tham chiếu của biến a và giá trị của param chính là giá trị của biến a = 1. kết thúc hàm ta sẽ có a = 2
    Còn nếu truyền vào hàm bằng out param, lúc này biến a is nothing, hàm sẽ phải khởi tạo lại gt cho a, và phụ thuộc vào giá trị khởi tạo đó để tiếp tục xử lý để đưa ra kết quả cuối cho a.
    Các trường hợp sử dụng 2 loại này rất khác nhau. Sử dụng ref khi giá trị của biến trước đó có ý nghĩa với hàm, còn sử dụng out khi giá trị của biến trước đó không có ý nghĩa gì với hàm.

  7. #7
    Ngày gia nhập
    12 2008
    Bài viết
    53

    Các trường hợp sử dụng 2 loại này rất khác nhau. Sử dụng ref khi giá trị của biến trước đó có ý nghĩa với hàm, còn sử dụng out khi giá trị của biến trước đó không có ý nghĩa gì với hàm.
    Anh có thể cho một vd hay một bài toán thể hiện một tác dụng cụ thể nhất dc không?
    Nói như anh và anh Đ.Khanh thì em chưa hình dung chính xác dc công dụng một cách cụ thể và mạnh mẽ -cái thằng ref và thằng out ứng dụng dc những công việc gì khi áp dụng vào lập trình (VD như Game hay phần mềm chẳng hạn...

  8. #8
    Ngày gia nhập
    03 2009
    Bài viết
    29

    Ke ke, mình có một ví dụ tượng hình cho các bạn, khỏi phải đọc quá nhiều code mà vẫn nắm được mặt trời chân lý, sau tha hồ mà nhói trong tim ^^
    • Ref là gì ?

      Nó giống như việc tôi bảo bạn:
      "Cho em vay ít tiền. Anh REF bảo kê cho em."
      Bạn sẽ bảo:
      "Được. Lần trước mày vay và có trả tao. Đưa ví hay cái gì đó mày dùng để đựng tiền cho tao."
      Tôi sẽ khúm núm:
      "Đây ạ, ví em anh tùy nghi sài." (và đưa cho bạn - Lúc này ví tôi Rỗng hoặc có một ít tiền)
      Bạn sẽ đặt vào đó cho tôi một ít tiền và trả lại ví cho tôi. - Lúc này ví tôi có thêm một ít tiền của bạn.
      Vậy, ở đây, tôi phải có một cái ví VÀ có uy tín từ trước để bạn tin và đặt tiền vào đó. Bạn chú ý nhé, tôi có cái ví và có uy tín. Cái ví là Biến, và uy tín của tôi là giá trị của tôi, đã được xác lập trước đó, đi kèm cùng cái ví.

      OK, ta sang ví dụ tiếp theo:
    • Out là gì ?
      Vẫn như trên:
      Tôi hỏi bạn
      "Cho em vay ít tiền. Anh REF bảo kê cho em."
      Bạn sẽ bảo: (giả sử lúc trước tôi mượn nhưng không giả bạn)
      "KHÔNG. Mày vay lần trước nhưng không giả tao. Thằng REF đó không có quyền bảo kê trong trường hợp này. 1/4 của lít ngay!"
      Tôi sẽ bảo:
      "Mịa, thằng keo kiệt." Rồi biến
      Nhưng giả sử tôi bảo:
      "Cho em vay ít tiền. Anh OUT bảo kê cho em."
      Bạn sẽ bảo: (giả sử lúc trước tôi mượn nhưng vẫn không giả bạn)
      "ĐƯỢC. Tuy mày chưa trả tao tiền lần trước nhưng tao vẫn đưa tiền cho mày lần này. Đưa ví đây."
      Và cuộc vay mượn được diễn ra. Vậy, tôi vẫn phải có ví tiền (Biến) và chẳng cần có uy tín quái gì, chỉ cần đại ca OUT bảo trợ cho tôi là được. Nhưng nếu tôi muốn vay tiền, trong khi tôi ko có uy tín, mà lại nhờ REF bảo trợ thì sẽ bị đá ngay.

      Đó, đó là sự khác nhau của 2 thằng REF và OUT.

      Tớ hay cố gắng tượng hình hóa cho vui, dễ truyền đạt về sau và dễ nhớ.


    NÓI LÀ LÀM, không được thì thôi

  9. #9
    Ngày gia nhập
    06 2009
    Bài viết
    1

    Trích dẫn Nguyên bản được gửi bởi hutboy Xem bài viết
    Ke ke, mình có một ví dụ tượng hình cho các bạn, khỏi phải đọc quá nhiều code mà vẫn nắm được mặt trời chân lý, sau tha hồ mà nhói trong tim ^^
    • Ref là gì ?

      Nó giống như việc tôi bảo bạn:
      "Cho em vay ít tiền. Anh REF bảo kê cho em."
      Bạn sẽ bảo:
      "Được. Lần trước mày vay và có trả tao. Đưa ví hay cái gì đó mày dùng để đựng tiền cho tao."
      Tôi sẽ khúm núm:
      "Đây ạ, ví em anh tùy nghi sài." (và đưa cho bạn - Lúc này ví tôi Rỗng hoặc có một ít tiền)
      Bạn sẽ đặt vào đó cho tôi một ít tiền và trả lại ví cho tôi. - Lúc này ví tôi có thêm một ít tiền của bạn.
      Vậy, ở đây, tôi phải có một cái ví VÀ có uy tín từ trước để bạn tin và đặt tiền vào đó. Bạn chú ý nhé, tôi có cái ví và có uy tín. Cái ví là Biến, và uy tín của tôi là giá trị của tôi, đã được xác lập trước đó, đi kèm cùng cái ví.

      OK, ta sang ví dụ tiếp theo:
    • Out là gì ?
      Vẫn như trên:
      Tôi hỏi bạn
      "Cho em vay ít tiền. Anh REF bảo kê cho em."
      Bạn sẽ bảo: (giả sử lúc trước tôi mượn nhưng không giả bạn)
      "KHÔNG. Mày vay lần trước nhưng không giả tao. Thằng REF đó không có quyền bảo kê trong trường hợp này. 1/4 của lít ngay!"
      Tôi sẽ bảo:
      "Mịa, thằng keo kiệt." Rồi biến
      Nhưng giả sử tôi bảo:
      "Cho em vay ít tiền. Anh OUT bảo kê cho em."
      Bạn sẽ bảo: (giả sử lúc trước tôi mượn nhưng vẫn không giả bạn)
      "ĐƯỢC. Tuy mày chưa trả tao tiền lần trước nhưng tao vẫn đưa tiền cho mày lần này. Đưa ví đây."
      Và cuộc vay mượn được diễn ra. Vậy, tôi vẫn phải có ví tiền (Biến) và chẳng cần có uy tín quái gì, chỉ cần đại ca OUT bảo trợ cho tôi là được. Nhưng nếu tôi muốn vay tiền, trong khi tôi ko có uy tín, mà lại nhờ REF bảo trợ thì sẽ bị đá ngay.

      Đó, đó là sự khác nhau của 2 thằng REF và OUT.

      Tớ hay cố gắng tượng hình hóa cho vui, dễ truyền đạt về sau và dễ nhớ.



    có bạn ở phía trên nói, nếu sử dụng out cho biến đã có giá trị ban đầu thì nó sẽ khởi tạo lại.

    Vậy thì khi bạn mượn tiền do OUT bảo kê.

    Đưa ví cho người kia để bỏ tiền vào (nhưng trong bóp còn tiền thì nó sẽ cộng thêm tiền hay là lấy hết tiền trong đó ra rồi mới bỏ tiền mới vô)

  10. #10
    Ngày gia nhập
    03 2011
    Bài viết
    2

    Trích dẫn Nguyên bản được gửi bởi tranngoclan1987 Xem bài viết
    có bạn ở phía trên nói, nếu sử dụng out cho biến đã có giá trị ban đầu thì nó sẽ khởi tạo lại.

    Vậy thì khi bạn mượn tiền do OUT bảo kê.

    Đưa ví cho người kia để bỏ tiền vào (nhưng trong bóp còn tiền thì nó sẽ cộng thêm tiền hay là lấy hết tiền trong đó ra rồi mới bỏ tiền mới vô)
    theo mình nghĩ thì nó sẽ "lấy tiền cũ ra và bỏ tiền mới vào"..
    nhưng mà nếu đã có giá trị ban đầu tức là ta đã có uy tín,thì ta lại sử dùng ref chứ chả tội gì dùng out cả..

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn