Methods and Functions

Learn to organize and reuse code with methods and functions in C#

What are Methods?

Methods (also called functions) are reusable blocks of code that perform specific tasks. They help organize code, reduce repetition, and make programs more maintainable.

Method Syntax

The basic syntax of a C# method:

MethodSyntax.cs
// Method declaration
[access modifier] [static] return_type MethodName(parameter_list)
{
    // Method body
    // Optional return statement
}

// Example method
public static void SayHello()
{
    Console.WriteLine("Hello from a method!");
}

// Calling the method
SayHello();

Basic Methods

Void Methods (No Return Value)

VoidMethods.cs
using System;

class Program
{
    static void Main(string[] args)
    {
        DisplayWelcomeMessage();
        ShowCurrentTime();
        DrawLine();
    }

    // Method with no parameters and no return value
    static void DisplayWelcomeMessage()
    {
        Console.WriteLine("Welcome to C# Methods!");
        Console.WriteLine("Let's learn about functions.");
    }

    // Another void method
    static void ShowCurrentTime()
    {
        DateTime now = DateTime.Now;
        Console.WriteLine($"Current time: {now:yyyy-MM-dd HH:mm:ss}");
    }

    // Simple utility method
    static void DrawLine()
    {
        Console.WriteLine("================================");
    }
}

Methods with Parameters

MethodsWithParameters.cs
static void Main(string[] args)
{
    // Calling methods with different parameters
    Greet("Alice");
    Greet("Bob");

    PrintPersonInfo("Charlie", 25);
    PrintPersonInfo("Diana", 30);

    RepeatMessage("Hello!", 3);
}

// Method with one parameter
static void Greet(string name)
{
    Console.WriteLine($"Hello, {name}!");
}

// Method with multiple parameters
static void PrintPersonInfo(string name, int age)
{
    Console.WriteLine($"Name: {name}");
    Console.WriteLine($"Age: {age}");
    Console.WriteLine($"Is adult: {age >= 18}");
    Console.WriteLine();
}

// Method with parameters of different types
static void RepeatMessage(string message, int times)
{
    for (int i = 0; i < times; i++)
    {
        Console.WriteLine($"{i + 1}. {message}");
    }
}

Methods with Return Values

Basic Return Methods

ReturnMethods.cs
static void Main(string[] args)
{
    // Using methods that return values
    int sum = AddNumbers(10, 20);
    Console.WriteLine($"Sum: {sum}");

    double area = CalculateCircleArea(5.0);
    Console.WriteLine($"Circle area: {area:F2}");

    string fullName = GetFullName("John", "Doe");
    Console.WriteLine($"Full name: {fullName}");

    bool isEven = IsEvenNumber(42);
    Console.WriteLine($"42 is even: {isEven}");
}

// Method returning an integer
static int AddNumbers(int a, int b)
{
    return a + b;
}

// Method returning a double
static double CalculateCircleArea(double radius)
{
    const double PI = 3.14159;
    return PI * radius * radius;
}

// Method returning a string
static string GetFullName(string firstName, string lastName)
{
    return $"{firstName} {lastName}";
}

// Method returning a boolean
static bool IsEvenNumber(int number)
{
    return number % 2 == 0;
}

Complex Return Examples

ComplexReturns.cs
static void Main(string[] args)
{
    // Methods returning calculated values
    int max = FindMaximum(15, 23, 8);
    Console.WriteLine($"Maximum: {max}");

    string grade = CalculateGrade(87);
    Console.WriteLine($"Grade: {grade}");

    double temperature = ConvertToFahrenheit(25.0);
    Console.WriteLine($"25°C = {temperature:F1}°F");
}

// Method with multiple calculations
static int FindMaximum(int a, int b, int c)
{
    if (a >= b && a >= c)
        return a;
    else if (b >= a && b >= c)
        return b;
    else
        return c;
}

// Method with conditional returns
static string CalculateGrade(int score)
{
    if (score >= 90)
        return "A";
    else if (score >= 80)
        return "B";
    else if (score >= 70)
        return "C";
    else if (score >= 60)
        return "D";
    else
        return "F";
}

// Method with formula calculation
static double ConvertToFahrenheit(double celsius)
{
    return (celsius * 9.0 / 5.0) + 32.0;
}

Method Overloading

You can create multiple methods with the same name but different parameters:

MethodOverloading.cs
static void Main(string[] args)
{
    // Same method name, different parameters
    PrintInfo("Alice");                    // Calls version with string
    PrintInfo(25);                         // Calls version with int
    PrintInfo("Bob", 30);                  // Calls version with string and int
    PrintInfo(15.5, 25.3);                // Calls version with two doubles
}

// Method overloads - same name, different parameters
static void PrintInfo(string name)
{
    Console.WriteLine($"Name: {name}");
}

static void PrintInfo(int age)
{
    Console.WriteLine($"Age: {age}");
}

static void PrintInfo(string name, int age)
{
    Console.WriteLine($"Name: {name}, Age: {age}");
}

static void PrintInfo(double width, double height)
{
    Console.WriteLine($"Dimensions: {width} x {height}");
    Console.WriteLine($"Area: {width * height}");
}

Default Parameters

You can provide default values for parameters:

DefaultParameters.cs
static void Main(string[] args)
{
    // Using default parameters
    CreateUser("Alice");                           // Uses default role
    CreateUser("Bob", "admin");                   // Overrides default role
    CreateUser("Charlie", "user", true);         // Overrides both defaults

    // Calculate with defaults
    double interest1 = CalculateInterest(1000);              // Default rate and years
    double interest2 = CalculateInterest(1000, 0.05);        // Custom rate, default years
    double interest3 = CalculateInterest(1000, 0.03, 10);    // All custom values

    Console.WriteLine($"Interest scenarios: {interest1:C}, {interest2:C}, {interest3:C}");
}

// Method with default parameters
static void CreateUser(string username, string role = "user", bool isActive = true)
{
    Console.WriteLine($"User: {username}");
    Console.WriteLine($"Role: {role}");
    Console.WriteLine($"Active: {isActive}");
    Console.WriteLine();
}

// Method with multiple defaults
static double CalculateInterest(double principal, double rate = 0.02, int years = 5)
{
    return principal * rate * years;
}

Named Parameters

You can specify parameters by name when calling methods:

NamedParameters.cs
static void Main(string[] args)
{
    // Using named parameters
    BookFlight(
        destination: "New York",
        departure: "Los Angeles",
        passengers: 2,
        date: DateTime.Today.AddDays(30)
    );

    // Named parameters allow different order
    BookFlight(
        passengers: 1,
        destination: "Chicago",
        date: DateTime.Today.AddDays(7),
        departure: "Miami"
    );

    // Mix positional and named parameters
    BookFlight("Boston", passengers: 3, date: DateTime.Today.AddDays(14), departure: "Seattle");
}

static void BookFlight(string destination, string departure = "Local Airport",
                      int passengers = 1, DateTime? date = null)
{
    DateTime flightDate = date ?? DateTime.Today.AddDays(7);

    Console.WriteLine("=== Flight Booking ===");
    Console.WriteLine($"From: {departure}");
    Console.WriteLine($"To: {destination}");
    Console.WriteLine($"Passengers: {passengers}");
    Console.WriteLine($"Date: {flightDate:yyyy-MM-dd}");
    Console.WriteLine();
}

Ref and Out Parameters

Ref Parameters

ref allows methods to modify the original variable:

RefParameters.cs
static void Main(string[] args)
{
    int number = 10;
    Console.WriteLine($"Before: {number}");

    DoubleValue(ref number);
    Console.WriteLine($"After: {number}");

    // Swapping values
    int a = 5, b = 15;
    Console.WriteLine($"Before swap: a = {a}, b = {b}");

    Swap(ref a, ref b);
    Console.WriteLine($"After swap: a = {a}, b = {b}");
}

// Method using ref parameter
static void DoubleValue(ref int value)
{
    value *= 2;  // Modifies the original variable
}

// Swapping two values using ref
static void Swap(ref int x, ref int y)
{
    int temp = x;
    x = y;
    y = temp;
}

Out Parameters

out parameters don't need to be initialized before passing:

OutParameters.cs
static void Main(string[] args)
{
    // Out parameters - don't need initialization
    bool success = TryParseAge("25", out int age);

    if (success)
    {
        Console.WriteLine($"Parsed age: {age}");
    }
    else
    {
        Console.WriteLine("Failed to parse age");
    }

    // Multiple out parameters
    CalculateStats(new int[] { 1, 2, 3, 4, 5 }, out double average, out int sum);
    Console.WriteLine($"Average: {average}, Sum: {sum}");

    // Out with discard
    TryParseAge("invalid", out _);  // Discard the out value
}

// Method with out parameter
static bool TryParseAge(string input, out int age)
{
    if (int.TryParse(input, out age) && age >= 0 && age <= 150)
    {
        return true;
    }

    age = 0;  // Must assign a value to out parameter
    return false;
}

// Method with multiple out parameters
static void CalculateStats(int[] numbers, out double average, out int sum)
{
    sum = 0;
    foreach (int num in numbers)
    {
        sum += num;
    }

    average = (double)sum / numbers.Length;
}

Variable Number of Parameters (params)

Use params to accept a variable number of arguments:

ParamsExample.cs
using System.Linq;

static void Main(string[] args)
{
    // Variable number of parameters
    int sum1 = Sum(1, 2, 3);
    int sum2 = Sum(1, 2, 3, 4, 5, 6);
    int sum3 = Sum();  // No parameters

    Console.WriteLine($"Sums: {sum1}, {sum2}, {sum3}");

    // With mixed parameters
    PrintReport("Monthly Sales", 1000, 1200, 950, 1100);
    PrintReport("Quarterly Results", 3000, 3200, 2800);
}

// Method with params keyword
static int Sum(params int[] numbers)
{
    int total = 0;
    foreach (int num in numbers)
    {
        total += num;
    }
    return total;
}

// Mixed regular and params parameters
static void PrintReport(string title, params double[] values)
{
    Console.WriteLine($"\n=== {title} ===");

    if (values.Length == 0)
    {
        Console.WriteLine("No data available");
        return;
    }

    for (int i = 0; i < values.Length; i++)
    {
        Console.WriteLine($"Period {i + 1}: {values[i]:C}");
    }

    double average = values.Average();
    Console.WriteLine($"Average: {average:C}");
}

Expression-bodied Methods

C# allows concise method syntax for simple methods:

ExpressionBodied.cs
static void Main(string[] args)
{
    // Using expression-bodied methods
    Console.WriteLine($"Square of 5: {Square(5)}");
    Console.WriteLine($"Is 'hello' long? {IsLongString("hello")}");

    GreetPerson("Alice");

    string formatted = FormatCurrency(1234.56);
    Console.WriteLine(formatted);
}

// Expression-bodied methods (C# 6+)
static int Square(int x) => x * x;

static bool IsLongString(string text) => text.Length > 10;

static void GreetPerson(string name) => Console.WriteLine($"Hello, {name}!");

static string FormatCurrency(double amount) => $"${amount:F2}";

// Traditional equivalent methods:
/*
static int Square(int x)
{
    return x * x;
}

static bool IsLongString(string text)
{
    return text.Length > 10;
}
*/

Local Functions

You can define functions inside other methods:

LocalFunctions.cs
static void Main(string[] args)
{
    ProcessNumbers();
    CalculateFactorial();
}

static void ProcessNumbers()
{
    // Local function defined inside the method
    bool IsValidNumber(int num)
    {
        return num >= 0 && num <= 1000;
    }

    string FormatResult(int num, bool isValid)
    {
        return isValid ? $"{num} is valid" : $"{num} is invalid";
    }

    // Using local functions
    int[] numbers = { 50, -10, 1500, 200 };

    foreach (int num in numbers)
    {
        bool valid = IsValidNumber(num);
        Console.WriteLine(FormatResult(num, valid));
    }
}

static void CalculateFactorial()
{
    // Recursive local function
    long Factorial(int n)
    {
        if (n <= 1)
            return 1;
        return n * Factorial(n - 1);
    }

    Console.WriteLine("\nFactorials:");
    for (int i = 1; i <= 5; i++)
    {
        Console.WriteLine($"{i}! = {Factorial(i)}");
    }
}

Method Best Practices

Keep Methods Focused

BestPractices.cs
// Good: Single responsibility
static double CalculateCircleArea(double radius)
{
    if (radius < 0)
        throw new ArgumentException("Radius cannot be negative");

    return Math.PI * radius * radius;
}

// Good: Clear, descriptive name
static bool IsValidEmail(string email)
{
    return !string.IsNullOrEmpty(email) && email.Contains("@") && email.Contains(".");
}

// Good: Input validation
static int Divide(int dividend, int divisor)
{
    if (divisor == 0)
        throw new ArgumentException("Cannot divide by zero");

    return dividend / divisor;
}

// Good: Meaningful return values
static (bool success, int value) TryParsePositiveInt(string input)
{
    if (int.TryParse(input, out int result) && result > 0)
    {
        return (true, result);
    }
    return (false, 0);
}

Practical Example: Text Processing Utility

TextProcessor.cs
using System;
using System.Text;

class TextProcessor
{
    static void Main(string[] args)
    {
        Console.WriteLine("=== Text Processing Utility ===\n");

        string text = "Hello World! This is a sample text for processing.";
        Console.WriteLine($"Original: {text}\n");

        // Demonstrate various text processing methods
        ShowTextStats(text);
        ShowTextTransformations(text);
        ShowWordOperations(text);
    }

    static void ShowTextStats(string text)
    {
        Console.WriteLine("=== Text Statistics ===");
        Console.WriteLine($"Character count: {CountCharacters(text)}");
        Console.WriteLine($"Word count: {CountWords(text)}");
        Console.WriteLine($"Sentence count: {CountSentences(text)}");
        Console.WriteLine($"Vowel count: {CountVowels(text)}");
        Console.WriteLine();
    }

    static void ShowTextTransformations(string text)
    {
        Console.WriteLine("=== Text Transformations ===");
        Console.WriteLine($"Title case: {ToTitleCase(text)}");
        Console.WriteLine($"Reversed: {ReverseText(text)}");
        Console.WriteLine($"Remove vowels: {RemoveVowels(text)}");
        Console.WriteLine($"Acronym: {CreateAcronym(text)}");
        Console.WriteLine();
    }

    static void ShowWordOperations(string text)
    {
        Console.WriteLine("=== Word Operations ===");
        string[] words = GetWords(text);
        Console.WriteLine($"Longest word: {FindLongestWord(words)}");
        Console.WriteLine($"Shortest word: {FindShortestWord(words)}");
        Console.WriteLine($"Words with 5+ letters: {CountLongWords(words, 5)}");
        Console.WriteLine();
    }

    // Counting methods
    static int CountCharacters(string text) => text.Length;

    static int CountWords(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return 0;

        return text.Split(new char[] { ' ', '\t', '\n', '\r' },
                         StringSplitOptions.RemoveEmptyEntries).Length;
    }

    static int CountSentences(string text)
    {
        if (string.IsNullOrEmpty(text))
            return 0;

        int count = 0;
        foreach (char c in text)
        {
            if (c == '.' || c == '!' || c == '?')
                count++;
        }
        return count;
    }

    static int CountVowels(string text)
    {
        if (string.IsNullOrEmpty(text))
            return 0;

        string vowels = "aeiouAEIOU";
        int count = 0;

        foreach (char c in text)
        {
            if (vowels.Contains(c))
                count++;
        }

        return count;
    }

    // Transformation methods
    static string ToTitleCase(string text)
    {
        if (string.IsNullOrEmpty(text))
            return text;

        string[] words = text.Split(' ');
        StringBuilder result = new StringBuilder();

        foreach (string word in words)
        {
            if (word.Length > 0)
            {
                string titleWord = char.ToUpper(word[0]) + word.Substring(1).ToLower();
                result.Append(titleWord + " ");
            }
        }

        return result.ToString().Trim();
    }

    static string ReverseText(string text)
    {
        if (string.IsNullOrEmpty(text))
            return text;

        char[] chars = text.ToCharArray();
        Array.Reverse(chars);
        return new string(chars);
    }

    static string RemoveVowels(string text)
    {
        if (string.IsNullOrEmpty(text))
            return text;

        string vowels = "aeiouAEIOU";
        StringBuilder result = new StringBuilder();

        foreach (char c in text)
        {
            if (!vowels.Contains(c))
                result.Append(c);
        }

        return result.ToString();
    }

    static string CreateAcronym(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return "";

        string[] words = text.Split(new char[] { ' ', '\t', '\n', '\r' },
                                   StringSplitOptions.RemoveEmptyEntries);
        StringBuilder acronym = new StringBuilder();

        foreach (string word in words)
        {
            if (word.Length > 0 && char.IsLetter(word[0]))
            {
                acronym.Append(char.ToUpper(word[0]));
            }
        }

        return acronym.ToString();
    }

    // Word analysis methods
    static string[] GetWords(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return new string[0];

        return text.Split(new char[] { ' ', '\t', '\n', '\r', '.', '!', '?' },
                         StringSplitOptions.RemoveEmptyEntries);
    }

    static string FindLongestWord(string[] words)
    {
        if (words.Length == 0)
            return "";

        string longest = words[0];
        foreach (string word in words)
        {
            if (word.Length > longest.Length)
                longest = word;
        }

        return longest;
    }

    static string FindShortestWord(string[] words)
    {
        if (words.Length == 0)
            return "";

        string shortest = words[0];
        foreach (string word in words)
        {
            if (word.Length < shortest.Length)
                shortest = word;
        }

        return shortest;
    }

    static int CountLongWords(string[] words, int minimumLength)
    {
        int count = 0;
        foreach (string word in words)
        {
            if (word.Length >= minimumLength)
                count++;
        }

        return count;
    }
}

Key Takeaways

Methods are fundamental building blocks of C# programming. They help you:

  • Organize code into logical, reusable blocks
  • Reduce repetition by writing code once and using it multiple times
  • Improve maintainability by isolating functionality
  • Make debugging easier by testing individual components
  • Enable collaboration by creating clear interfaces between code sections

Practice creating methods with different signatures, return types, and parameter configurations to become proficient in C# programming structure and organization.

Last updated on