Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

การเรียกเมธอดแบบ Recursive ใน C#

ภาพรวม

Recursive Method (เมธอดเรียกตัวเอง) คือ เมธอดที่เรียกตัวเองภายในตัวเอง เพื่อแก้ปัญหาที่สามารถแบ่งเป็น Sub-problems ที่มีโครงสร้างเดียวกัน ต้องมี Base Case (กรณีฐาน) เพื่อหยุด Recursion ไม่งั้นจะเกิด Stack Overflow

ตัวอย่าง: Factorial (แฟกทอเรียล)

n! = n × (n-1) × ... × 1, โดย 0! = 1, 1! = 1

using System;

namespace MyApplication
{
    class Factorial
    {
        public int Calculate(int n)
        {
            // Base Case: หยุด Recursion
            if (n <= 1)
                return 1;
            
            // Recursive Case: เรียกตัวเองด้วย n-1
            return n * Calculate(n - 1);
        }
        
        static void Main(string[] args)
        {
            int value = 5;
            Factorial fact = new Factorial();
            int result = fact.Calculate(value);
            
            Console.WriteLine("{0}! = {1}", value, result); // 5! = 120
            Console.ReadLine();
        }
    }
}

ผลลัพธ์

5! = 120

การทำงานของ Recursive Factorial (5!)

Calculate(5)
  = 5 * Calculate(4)
  = 5 * (4 * Calculate(3))
  = 5 * 4 * (3 * Calculate(2))
  = 5 * 4 * 3 * (2 * Calculate(1))
  = 5 * 4 * 3 * 2 * 1          // Base Case: Calculate(1) = 1
  = 120

โครงสร้าง Recursive Method

ReturnType RecursiveMethod(Parameters)
{
    // 1. Base Case(s) - เงื่อนไขหยุด (สำคัญที่สุด!)
    if (baseCondition)
        return baseValue;
    
    // 2. Recursive Case - เรียกตัวเองด้วย Problem Size ที่เล็กลง
    return Combine(CurrentStep, RecursiveMethod(SimplifiedParameters));
}

ตัวอย่างเพิ่มเติม: Fibonacci

public int Fibonacci(int n)
{
    if (n <= 1) return n; // Base Cases: F(0)=0, F(1)=1
    return Fibonacci(n - 1) + Fibonacci(n - 2);
}

// หมายเหตุ: วิธีนี้ช้า O(2^n) ควรใช้ Memoization หรือ Iterative

การปรับปรุงประสิทธิภาพ: Memoization

private Dictionary memo = new Dictionary();

public int FibonacciMemo(int n)
{
    if (n <= 1) return n;
    
    if (memo.TryGetValue(n, out int cached))
        return cached;
    
    int result = FibonacciMemo(n - 1) + FibonacciMemo(n - 2);
    memo[n] = result;
    return result;
}

Iterative Version (แปลง Recursion เป็น Loop)

public int FactorialIterative(int n)
{
    int result = 1;
    for (int i = 2; i <= n; i++)
        result *= i;
    return result;
}

// Stack Overflow Risk: Recursion Depth ~ 10,000-100,000 (ขึ้นอยู่กับ Stack Size)
// Iterative ไม่มีปัญหา Stack Overflow

ข้อสังเกตสำคัญ

  • Base Case บังคับ - ไม่มี = Infinite Recursion = StackOverflowException
  • แต่ละ Recursive Call ใช้ Stack Frame ~ 1KB → จำกัดความลึก
  • Tail Recursion Optimization: C# Compiler/CLR ไม่รับประกัน (ต่างจาก F#)
  • ใช้ Recursion เมื่อ: Tree/Graph Traversal, Divide & Conquer, Backtracking, Parser
  • หลีกเลี่ยง Recursion เมื่อ: Iterative เขียนง่ายเท่ากัน, Performance Critical, Deep Recursion
  • C# 7.0+ ใช้ ref return และ local functions ช่วย Recursion ได้