return statement

ถ้า method ที่เราสร้างขึ้น มีการส่งค่ากลับ(non-void method) เราจะต้องมีการส่งค่ากลับในบรรทัดใดบรรทัดหนึ่งใน method นั้น โดยใช้statement return ตามด้วยค่าที่ต้องการส่งกลับ แล้วจากนั้น โปรแกรมออกจาก method กลับไปทำงานต่อใน statement ถัดจาก statement ที่เรียก method นั้น

int Square(int n) {
    return n * n;
    Console.WriteLine("This line never been printed");
}

หาก method นั้น เป็น void method เมื่อรันบรรทัดสุดท้ายของ method เสร็จโปรแกรมก็จะออกจาก method นั้น แต่ถ้าเราต้องการให้โปรแกรมออกจาก method ก่อนเวลา ก็ทำได้โดยเขียน statement return ลงไป มันก็จะหลุดออกจาก method นั้นไปเช่นเดียวกัน

static void WriteInverseCase(string s) {
    if(s == null) {
        return;
    }

    for(int i = 0; i < s.Length; i++) {
        if(Char.IsLower(s[i])) {
            Console.Write(s[i].ToUpper());
        else if(Char.IsUpper(s[i])) {
            Console.Write(s[i].ToLower());
        } else {
            Console.Write(s[i]);
        }
    }
    Console.WriteLine();
}

ลองทำดู

จะเกิดอะไรขึ้นเมื่อเรียก method F()
int F() {
    return 0;
    Console.WriteLine("still here");
    return 1;
}
และ method G() นี้จะผ่านการคอมไพล์หรือไม่
void G() {
    return 2;
}

Parameter passing

parameter ก็คือข้อมูลที่ส่งเข้าไปใน method เพื่อให้ method นำค่าเหล่านั้นไปใช้ในการทำงานบางอย่าง โดยมีคำศัพท์เฉพาะไว้เรียกสองคำ parameter ตรงตำแหน่งผู้เรียก method นั้นจะมีชื่อเรียกเต็ม ๆ ว่า actual parameter(parameter แท้จริง) หรือมักจะถูกเรียกว่า argument
ถ้าเป็น parameter ในตำแน่งของ method นั้นจะถูกเรียกว่า formal parameter(parameter ทางการ) แต่ก็จะถูกเรียกสั้น ๆ ว่า parameter

การส่งค่า parameter ให้ method นั้นมีด้วยกันสองวิธี

  1. Pass by value การส่งค่าวิธีนี้มีอยู่ในทุก ๆ ภาษา โดย argument นั้นจะเป็นค่าคงที่ ตัวแปร หรือ expression ใด ๆ ก็ได้ โดยถ้าเป็นตัวแปรหรือ expression ก็จะ copy ค่าของตัวแปรหรือ expression นั้นส่งไปให้เท่านั้น ข้อเสียของวิธีนั้นก็คือถ้า ค่าที่ส่งมีขนาดใหญ่(เช่น string, struct(สำหรับภาษา C) หรือ record(สำหรับ Pascal)) จะทำให้เกิด overhead ในการเรียก method แต่ละครั้งสูงมาก เพราะเราต้องสร้างตัวแปรชั่วคราวขึ้นมาเก็บค่าที่ส่งให้กับ method
  2. Pass by reference หน้า parameter ที่จะต้องการให้ pass by reference จะต้องมี keyword ว่า ref ไว้ข้างหน้า type ของ parameter argument จะต้องเป็นตัวแปรเท่านั้น เพราะว่าการส่งค่าพารามิเตอร์แบบนี้ คือการส่ง reference หรือตำแหน่งของตัวแปรเหล่านั้นไปให้กับ method แล้ว method นั้นจะเอาตัวแปรนั้นไปใช้งานโดยตรง ภาษายอดนิยมหลาย ๆ ภาษา ไม่มีวิธีการนี้ เช่น C, C++, Java นั้นสามารถ pass by value ได้อย่างเดียว วิธีแก้ไขของ C/C++ คือใช้ pointer ช่วย โดยการให้ pointer ชี้ไปที่ตัวแปรที่ต้องการ แล้วส่ง pointer ตัวนั้นแบบ by value ไปแทน Java ก็เช่นเดียวกัน เพราะการส่ง reference ของ instance ไป ก็เปรียบเหมือนการส่ง pointer ของตัวแปรไปให้(ดังนั้นแล้วอย่าพูดว่า Java จะ pass by value เฉพาะ primitive type และใช้วิธี pass by reference กับ instance ของคลาส เพราะ Java สามารถ pass by value ได้อย่างเดียว)
    กลับมาพูดถึงเรื่อง pass by reference ต่อ ข้อดีของวิธีนี้คือประหยัดเนื้อที่และ memory ในการส่ง
    ข้อเสียคือถ้าผู้ใช้ method นั้นไม่รู้ว่า method ที่ตนเองเรียกนั้นจะรับค่า parameter นั้นไปแก้ไขรึเปล่า บางทีอาจจะทำให้ค่าของตัวแปรนั้นเปลี่ยนไปโดยไม่รู้ตัว ใน C# จึงแก้ปัญหาโดยการที่ขณะเรียก method นั้นต้องระบุ keyword ว่า ref ไว้ที่หน้า argument ตัวที่ตรงกับ parameter ที่รับค่าแบบ by reference ภาษาที่ไม่มีวิธีการส่งค่า parameter แบบนี้ จะไม่สามารถเขียน method บางอย่างเช่น swap ตัวเลขสองตัวได้(ใน C/C++ ใช้ pointer ช่วยได้ แต่ Java จะไม่สามารถเขียนได้เลย)

static long Factorial(int n) {
    if(n < 0) {
        return 0;
    }

    long fac = 1;

    for(int i = 1; i <= n; i++) {
        fac *= i;
    }

    return fac;
}

static void Swap(ref int x, ref int y) {
    int temp = x;
    x = y;
    y = temp;
}

static void Main() {
    for(int i = 1; i <= 10; i++) {
        Console.WriteLine("{0,2}! = {1,7}", i, Factorial(i));
    }

    int x = 1, y = 2;
    Console.WriteLine("Before swap x = {0}, y = {1}", x, y);
    Swap(ref x, ref y);
    Console.WriteLine("After swap x = {0}, y = {1}", x, y);
}
 1! =       1
 2! =       2
 3! =       6
 4! =      24
 5! =     120
 6! =     720
 7! =    5040
 8! =   40320
 9! =  362880
10! = 3628800
Before swap x = 1, y = 2
After swap x = 2, y = 1

Passing out parameter

การส่งค่าเข้า method สามารถทำได้โดยการส่งผ่าน parameter เข้าไปไม่จำกัดจำนวน ส่วนการส่งค่าออกก็คือการส่งมาทางค่าที่ถูก return และส่งค่ากลับมาได้ตัวเดียว แต่ถ้าเราต้องการส่งค่ากลับมาจาก method หลาย ๆ ค่า ปกติจะทำได้โดยการ pass by reference ตัวแปรไปแทน แต่ใน C# เราสามารถทำได้ โดยการใช้ keyword out วางหน้า argument และหน้า parameter

using System;
using System.IO;

class Parser {
    static void Parse(string line, out int errorcode) {
        ...
    }

    static void CheckError(int errorcode) {
        ...
    }

    static void Main(string[] args) {
        try {
            StreamReader inFile = File.OpenText(args[0]);

            string line;
            int errorCode = 0;

            while((line = inFile.ReadLine()) != null) {
                Parse(line, out errorCode);
                CheckError(errorCode);
            }
            inFile.Close();
        } catch(IOException) {
            // handle error
        }
    }
}
ข้อแตกต่างระหว่าง out กับ ref คือ
parameter ที่ถูกระบุด้วย ref จะต้องมีการกำหนดค่าก่อนจะส่งไปให้ method(ตามข้อกำหนดของ C# ที่จะต้องกำหนดค่าตัวแปรก่อนใช้งาน)
ต่างกับ parameter ที่ถูกระบุให้เป็น out ที่ไม่จำเป็นต้องกำหนดค่าก่อนส่งให้ method แต่ต้องมีการกำหนดค่าใน method ก่อนจะออกจาก method นั้น

ลอง complie code ด้านล่างนี้ดู

static void F(ref int x, out int y) {
    return;
}

public static void Main() {
    int x, y;
    F(ref x, out y);
}

จบแบบคาใจ เหมือนยังเีขียนไม่หมด ถ้าผมนึกออกว่าลืมอะไรจะเขียนตอนเก็บตกไว้อีกตอนละกันครับ


edit @ 2005/06/21 14:35:27 C++ มี pass by reference ครับ

Comment

Comment:

Tweet

ขอบคุณมากค่ะ ลองรันโค้ดแล้วเข้าใจเยอะเลย

#30 By Loveข้าบดินทร์ (124.122.158.82|124.122.158.82) on 2015-06-19 11:17

You're the grasteet! JMHO

#29 By Lvf1x3zj6q (174.55.79.97) on 2013-07-29 20:43

Callnig all cars, calling all cars, we're ready to make a deal.

#28 By lfDciw3xPwE (10.0.12.24, 71.40.58.99) on 2013-07-27 20:53

retcnlyu eybbrfoa tlafajmt

#27 By cmngsBkDIdipnUkZb (94.102.49.213) on 2009-08-15 03:57

gnmevhjq pesqpzfd pcewirfj

#26 By gHYfqkKuu (94.102.49.213) on 2009-08-15 02:36

hawnvubc ycttfywc bqvztldt

#25 By viUjcRJlCzXfgjSbhOG (94.102.49.213) on 2009-08-15 01:11

wshojker qdcuximj ieecqadk

#24 By RClluVZsDBFvdqJ (94.102.49.213) on 2009-08-14 23:46

nwovrkca mvwvavzs ecgfeumt

#23 By mpionVbtEVQLN (94.102.49.213) on 2009-08-14 22:17

grozkagg sludkrgr grvfdyqo

#22 By LfVlZzIotFTEPdG (94.102.49.213) on 2009-08-14 19:25

ddpjdnrv mohqgbuz ngwuejkf

#21 By gNAvIzRqKnujBT (94.102.49.213) on 2009-08-14 18:00

bhjbrmib ckibtufy yrxwqzji

#20 By UHVUqTehkSecDuhzOVF (94.102.49.213) on 2009-08-14 16:35

gnvmgddf ptajgxrh mpnicnsl

#19 By sUBZabACduKArstgU (94.102.49.213) on 2009-08-14 15:11

ihvhhubm qfejkhzc zvqwaynm

#18 By ybxdZdNOWVfexxdFnrn (89.248.172.50) on 2009-08-10 02:42

oguakwcg ntubmgmr gwugmryo

#17 By BHFxBFbssOGLbcV (89.248.172.50) on 2009-08-10 01:17

ketzikxw owfxwelf xvtavfvf

#16 By QPqKOQcEbvNMBUpJhqE (89.248.172.50) on 2009-08-09 23:54

qgorbnqg ghirirxo kbkghqsv

#15 By ZsWzTeUl (89.248.172.50) on 2009-08-09 22:30

guuvjtxr ovffmkqk ownnaduv

#14 By YDyGSPYkAhZXGdwl (89.248.172.50) on 2009-08-09 21:04

dwlemqzc ofgzszia kxwgwrxm

#13 By nPSBPazMYUxb (95.169.190.71) on 2009-08-01 12:55

ztrtkgqt amqcztnc jgrcokhv

#12 By VwUehjvmFlUjHRcypfZ (95.169.190.71) on 2009-08-01 11:34

vttafxls quqzzuny qfjonoru

#11 By nEcKsYrlj (95.169.190.71) on 2009-08-01 07:30

xHrVHY iexokuio xssesqbf unlqlcka

#10 By wjlKVeMMLZkzaORAe (89.248.172.50) on 2009-07-28 15:05

ขอคุงมากเลยครับ หามาตั้งนาน ส่งค่าแบบ reference ยังไง เพราะเคยใช้แต่ C++ ส่งค่าเป็น
pointer....

^^~ แหล่ม

#9 By gmax (125.26.37.84) on 2009-04-11 21:07

ดีมากเลย ผมได้ความรู้มากเลยครับ

#8 By pommatt (203.130.134.132) on 2008-01-07 21:12

#7 By (202.12.74.74) on 2007-10-30 18:31

fgdfgfgf

#6 By (125.27.128.254) on 2007-10-05 14:37

ตัวอย่างสุดท้าย out int y แล้ว return ค่าอะไรหรือครับ

#5 By (203.153.166.116) on 2007-04-05 10:44

ไม่เคยเขียน C# อะ เหอๆ แต่ได้ความรู้ขึ้นเยอะครับ

#4 By (203.147.16.208 /192.168.1.43) on 2005-07-04 10:55

ไม่รู้เรื่องเลย แหง่ว
kaze : ขอบคุณครับพี่ ผมเบลอจริง ๆ

#2 By T!D on 2005-06-21 14:37

C ไม่มี pass by reference <= ถูกต้องนะคร๊าบ
แตว่า่ C++ มี pass by reference ครับ

ex.
void f(int val, int& ref) { ... }

ตัวหลังเป็น pass by reference ครับ

อ้างอิงจาก The C++ Programming Language 3rd Edition (Stroustrap) หัวข้อ 7.2 Argument Passing หน้า 145-146

#1 By kaze on 2005-06-21 10:38