C# Методы

Метод — это блок кода, который организует набор связанных операторов вместе для выполнения конкретной задачи. Это реализация в C#повторного использования кодаиинкапсуляции логикиосновного механизма. Каждая программа на C# имеет по крайней мере одинMainМетод служит точкой входа в программу.

Использование метода требует двух шагов:Определение методаиВызов метода。


1. Определение методов

Базовый синтаксис определения метода в C# выглядит следующим образом:

<access modifier> <return type> <method name>(<parameter list>)
{
    method body
}

Метод состоит из следующих элементов:

  • Модификаторы доступа(Модификатор доступа): управляет видимостью метода, напримерpublic、private、protected、internal。
  • Тип возвращаемого значения(Тип возвращаемого значения): тип данных возвращаемого значения метода. Если метод не возвращает значение, используйтеvoid。
  • имя метода(Имя метода): уникальный идентификатор метода, соответствующий соглашениям именования PascalCase (например,FindMax、GetUserName)。
  • Список параметров(Список параметров): входные данные, которые получает метод, заключенные в круглые скобки. Параметры необязательны; метод может не иметь параметров.
  • тело метода(Тело метода): содержит код, реализующий функциональность, заключенный в фигурные скобки{}Окружите.

На следующем рисунке показана полная структура метода:

C# method structure parsing public int FindMax ( int num1, int num2 ) Access modifiers public / private Control visibility Return Type int / void Return value data type method name PascalCase Unique identifier Parameter list Type + name Separate multiple with commas { Method body — code that implements functionality } Method Body Full method signature: public int FindMax(int a, int b) Modifier → Return type → Method name → Parameter list

1.1 Первый пример метода

Далее определяетсяFindMaxМетод, который принимает два целых числа и возвращает большее из них:

Пример

using System;

namespace MethodDemo
{
    class NumberHelper
    {
        // Определите метод, который принимает два int и возвращает большее из них
        public int FindMax(int num1, int num2)
        {
            if (num1 > num2)
                return num1;
            else
                return num2;
        }

        static void Main(string[] args)
        {
            // Создать объект и вызвать метод
            NumberHelper helper = new NumberHelper();
            int result = helper.FindMax(100, 200);

            Console.WriteLine($"Максимальное значение: {result}");  // Максимальное значение: 200
        }
    }
}

Процесс вызова метода:

Method call flow caller FindMax(100, 200) Actual argument Method receives num1=100, num2=200 Execute method body Compare and return result return Return Value result = 200 1. Call the method, pass the actual arguments → 2. Formal parameters receive the values → 3. Execute the method body → 4. Return the result to the caller

Вызов из другого класса:Если метод объявлен какpublic, то его можно вызвать из других классов, создав экземпляр. Это основа повторного использования кода в объектно-ориентированном программировании.


2. Способы передачи параметров

C# предоставляет три способа передачи параметров в методы. Их основное различие заключается втом, совместно ли используется память:

Comparison of Three Parameter Passing Methods Pass by value (default) caller a = 100 Copy within the method x = 100 Mutually independent memory spaces Modifying x does not affect a a and b remain unchanged after swap(a, b) No extra keyword required void Swap(int x, int y) Pass by reference (ref) caller a = 200 Same address within the method ref x = 200 Share the same memory block Modifying x will change a After swap(ref a, ref b), the swap is successful Requires the ref keyword void Swap(ref int x, ref int y) Output parameter (out) caller a = 5 ← Output within the method out x = 5 The method must assign a value to the out parameter. No need to initialize before calling Can return multiple values Requires the out keyword void Calc(out int x, out int y)
Метод Ключевые слова Поведение Типичные сценарии
Передача по значению (нет) Копирует значение параметра; изменения внутри метода не влияют на исходную переменную. Большинство вызовов методов (по умолчанию)
Передача по ссылке ref Передача ссылки на переменную; изменения внутри метода изменят исходную переменную. Нужно изменять внешние переменные (например, обмен значениями)
Выходной параметр out Похоже на ref, но метод должен присвоить значение, и переменную не нужно инициализировать перед вызовом. Метод должен возвращать несколько значений

2.1 Передача по значению (по умолчанию)

Передача по значению используется по умолчанию. Значение аргумента будетскопированои передано параметру; изменения параметра внутри метода не повлияют на исходную переменную:

Пример

using System;

namespace ParameterDemo
{
    class Program
    {
        // Передача по значению: x и y — копии a и b
        public void Swap(int x, int y)
        {
            int temp = x;
            x = y;
            y = temp;
            Console.WriteLine($" Внутри метода: x={x}, y={y}");  // Обмен выполнен успешно
        }

        static void Main(string[] args)
        {
            var p = new Program();
            int a = 100, b = 200;

            Console.WriteLine($Перед вызовом: a={a}, b={b});
            p.Swap(a, b);
            Console.WriteLine($После вызова: a={a}, b={b});  // a, b не изменились!
        }
    }
}
调用前:a=100, b=200
  方法内:x=200, y=100
调用后:a=100, b=200

2.2 Передача по ссылке (ref)

ИспользованиеrefКлючевое слово передаётссылкуна переменную (адрес в памяти); изменения параметра внутри метода напрямую повлияют на исходную переменную. Обратите внимание, что ключевое слово также нужно указать при вызове.ref:

Пример

using System;

namespace ParameterDemo
{
    class Program
    {
        // Передача по ссылке: x и y напрямую ссылаются на память a、b
        public void Swap(ref int x, ref int y)
        {
            int temp = x;
            x = y;
            y = temp;
        }

        static void Main(string[] args)
        {
            var p = new Program();
            int a = 100, b = 200;

            Console.WriteLine($Перед вызовом: a={a}, b={b});
            p.Swap(ref a, ref b);  // При вызове также нужно добавить ref
            Console.WriteLine($После вызова: a={a}, b={b});  // Обмен выполнен успешно!
        }
    }
}
调用前:a=100, b=200
调用后:a=200, b=100

Разница между ref и out:refТребует, чтобы переменная перед передачейбыла уже инициализирована;outТогда это не требуется, но внутри методаout-параметру должно быть присвоено значениепрежде чем его можно использовать.

2.3 Выходные параметры (out)

outПараметры позволяют методуВозвращать несколько значений. ИrefРазница в том, что переменную не нужно инициализировать перед вызовом, но метод должен присвоить ей значение:

Пример

using System;

namespace ParameterDemo
{
    class Program
    {
        // out-параметр: метод отвечает за присваивание
        public void GetValues(out int x, out int y)
        {
            Console.Write("Введите первое значение:");
            x = Convert.ToInt32(Console.ReadLine());

            Console.Write("Введите второе значение:");
            y = Convert.ToInt32(Console.ReadLine());
            // Примечание: Все out-параметры должны быть присвоены до завершения метода, иначе возникает ошибка компиляции.
        }

        // Практический пример: шаблон TryParse
        public bool TryDivide(int a, int b, out double result)
        {
            if (b == 0)
            {
                result = 0;
                return false;  // Деление на ноль
            }
            result = (double)a / b;
            return true;
        }

        static void Main(string[] args)
        {
            var p = new Program();

            // параметры out не требуют инициализации
            int a, b;
            p.GetValues(out a, out b);
            Console.WriteLine($"a={a}, b={b}");

            // шаблон TryParse
            if (p.TryDivide(10, 3, out double res))
                Console.WriteLine($"10 / 3 = {res:F2}");  // 3.33
        }
    }
}

Начиная с C# 7.0, при вызове можно использоватьвстроенное объявлениеout-переменных, что делает код более кратким:

// C# 7.0+ 内联声明
if (int.TryParse("123", out int number))
    Console.WriteLine($"解析成功:{number}");

3. Рекурсивные методы

Рекурсия — это методвызова самого себяКаждый рекурсивный метод требует двух элементов:

  • Базовое условие(базовый случай): условие, которое завершает рекурсию, предотвращая бесконечную рекурсию.
  • Рекурсивный шаг(рекурсивный шаг): разбивает задачу на более мелкие подзадачи.

Классический пример — вычисление факториала $$n! = n \times (n-1)!$$:

Пример

using System;

namespace RecursionDemo
{
    class Program
    {
        // Рекурсивно вычислить факториал
        public int Factorial(int n)
        {
            // Базовое условие: 0! = 1, 1! = 1
            if (n <= 1)
                return 1;

            // Рекурсивный шаг: n! = n × (n-1)!
            return n * Factorial(n - 1);
        }

        static void Main(string[] args)
        {
            var p = new Program();
            Console.WriteLine($"6! = {p.Factorial(6)}");   // 720
            Console.WriteLine($"7! = {p.Factorial(7)}");   // 5040
            Console.WriteLine($"8! = {p.Factorial(8)}");   // 40320
        }
    }
}
6! = 720
7! = 5040
8! = 40320

Процесс развёртывания рекурсивных вызовов:

Factorial(4)
  = 4 × Factorial(3)
  = 4 × 3 × Factorial(2)
  = 4 × 3 × 2 × Factorial(1)
  = 4 × 3 × 2 × 1
  = 24

Примечание:Когда глубина рекурсии слишком велика, это может вызватьStackOverflowExceptionДля сценариев, чувствительных к производительности, рассмотрите использование цикла вместо этого.


4. Дополнительные возможности методов

4.1 Параметры по умолчанию и именованные параметры

C# позволяет задавать параметрамзначение по умолчанию, их можно опускать при вызове. В сочетании сименованными параметрамиможно также пропустить некоторые параметры и указать только следующие за ними:

Пример

using System;

namespace MethodFeatures
{
    class Program
    {
        // Параметр по умолчанию: power по умолчанию равен 2
        static double Power(double baseNum, int степень = 2)
        {
            double result = 1;
            for (int i = 0; i < power; i++)
                result *= baseNum;
            return result;
        }

        // Несколько параметров по умолчанию
        static void PrintInfo(string name, int age = 18, string city = "Unknown")
        {
            Console.WriteLine($"{name}, {age} years old, {city}");
        }

        static void Main(string[] args)
        {
            // Использование параметров по умолчанию
            Console.WriteLine(Power(3));       // 9.0 (используется power=2 по умолчанию)
            Console.WriteLine(Power(3, 3));    // 27.0

            // Именованные аргументы: пропустить age, указать только city
            PrintInfo(Xiaoming, city: "Beijing");
            // Вывод: Xiaoming, 18 лет, Beijing

            // Именованные аргументы могут быть в любом порядке
            PrintInfo(city: "Shanghai", name: Xiaohong, age: 25);
            // Вывод: Сяохун, 25 лет, Шанхай
        }
    }
}

4.2 Методы с телом-выражением

Когда тело метода содержит только один оператор, можно использовать=>Упрощённый синтаксис (C# 6.0+):

// 传统写法
public int Add(int a, int b)
{
    return a + b;
}

// 表达式体写法(等价)
public int Add(int a, int b) => a + b;

4.3 Перегрузка методов (Overloading)

В одном и том же классе может бытьнесколько методов с одинаковым именем, если списки параметров различаются (разные типы, количество или порядок параметров):

Пример

using System;

namespace MethodFeatures
{
    class Calculator
    {
        // Перегрузка 1: Add для двух int
        public int Add(int a, int b) => a + b;

        // Перегрузка 2: Add для трёх int
        public int Add(int a, int b, int c) => a + b + c;

        // Перегрузка 3: Add для двух double
        public double Add(double a, double b) => a + b;

        static void Main(string[] args)
        {
            var calc = new Calculator();
            Console.WriteLine(calc.Add(1, 2));         // 3 (вызов перегрузки 1)
            Console.WriteLine(calc.Add(1, 2, 3));      // 6 (вызов перегрузки 2)
            Console.WriteLine(calc.Add(1.5, 2.5));     // 4.0 (вызов перегрузки 3)
        }
    }
}

Итог

Особенности Синтаксис Описание
Определите метод int Add(int a, int b) { ... } Укажите тип возвращаемого значения, имя метода и параметры
Нет возвращаемого значения void DoSomething() { ... } voidУказывает, что значение не возвращается
Передача по значению void Foo(int x) Метод по умолчанию; изменения параметров не влияют на аргументы
Передача по ссылке void Foo(ref int x) Общая память; изменения отражаются в аргументах
Выходной параметр void Foo(out int x) Должен быть присвоен внутри метода; может возвращать несколько значений
Параметр по умолчанию void Foo(int x = 10) Можно опустить при вызове; используются значения по умолчанию
Именованные параметры Foo(city: "北京") Указывайте параметры по имени, порядок можно изменить
Тело выражения int Add(int a, int b) => a + b; Сокращённая запись для однострочных методов (C# 6.0+)
Перегрузка методов Одинаковое имя, разные параметры Компилятор автоматически выбирает на основе списка параметров
Другие расширения