DEV Community

Neeraj Sharma
Neeraj Sharma

Posted on

Methods and Functions in C#

Introduction

Methods are reusable blocks of code that perform specific tasks. They are fundamental to organizing code, reducing duplication, and making programs more maintainable. In this topic, we'll explore how to create, call, and effectively use methods in C#.

What is a Method?

A method is a code block that contains a series of statements. Methods are declared within classes and can be called multiple times from different parts of your program. They help in:

  • Code reusability
  • Modularity
  • Maintainability
  • Testing

Method Declaration Syntax

access-modifier return-type method-name(parameter-list)
{
    // Method body
    // Statements
}
Enter fullscreen mode Exit fullscreen mode

Basic Example

public static void SayHello()
{
    Console.WriteLine("Hello, World!");
}
Enter fullscreen mode Exit fullscreen mode

Method Components

1. Access Modifiers

Control the visibility of methods:

  • public: Accessible from anywhere
  • private: Accessible only within the same class (default)
  • protected: Accessible within the same class and derived classes
  • internal: Accessible within the same assembly

2. Return Types

Specify what type of value the method returns:

  • void: No return value
  • int, string, bool: Specific data types
  • Custom types: Classes, structs, etc.

3. Method Name

Should follow PascalCase naming convention and be descriptive:

public static int CalculateArea(int width, int height)
{
    return width * height;
}
Enter fullscreen mode Exit fullscreen mode

4. Parameters

Values passed to the method when called:

public static void GreetUser(string name, int age)
{
    Console.WriteLine($"Hello, {name}! You are {age} years old.");
}
Enter fullscreen mode Exit fullscreen mode

Calling Methods

Calling Void Methods

SayHello(); // No return value expected
Enter fullscreen mode Exit fullscreen mode

Calling Methods with Return Values

int area = CalculateArea(10, 5);
Console.WriteLine($"Area: {area}");
Enter fullscreen mode Exit fullscreen mode

Calling Methods with Parameters

GreetUser("John", 25);
Enter fullscreen mode Exit fullscreen mode

Parameter Types

Value Parameters (Default)

Changes to parameters don't affect the original values:

public static void ModifyValue(int number)
{
    number = 100; // This doesn't change the original value
}

int original = 50;
ModifyValue(original);
Console.WriteLine(original); // Still 50
Enter fullscreen mode Exit fullscreen mode

Reference Parameters (ref)

Changes to parameters affect the original values:

public static void ModifyReference(ref int number)
{
    number = 100; // This changes the original value
}

int original = 50;
ModifyReference(ref original);
Console.WriteLine(original); // Now 100
Enter fullscreen mode Exit fullscreen mode

Output Parameters (out)

Used to return multiple values from a method:

public static void GetCoordinates(out int x, out int y)
{
    x = 10;
    y = 20;
}

GetCoordinates(out int xCoord, out int yCoord);
Console.WriteLine($"X: {xCoord}, Y: {yCoord}"); // X: 10, Y: 20
Enter fullscreen mode Exit fullscreen mode

Parameter Arrays (params)

Allows passing a variable number of arguments:

public static int SumNumbers(params int[] numbers)
{
    int sum = 0;
    foreach (int number in numbers)
    {
        sum += number;
    }
    return sum;
}

int total = SumNumbers(1, 2, 3, 4, 5);
Console.WriteLine(total); // 15
Enter fullscreen mode Exit fullscreen mode

Method Overloading

Multiple methods with the same name but different parameters:

public static int Add(int a, int b)
{
    return a + b;
}

public static double Add(double a, double b)
{
    return a + b;
}

public static int Add(int a, int b, int c)
{
    return a + b + c;
}

// Usage
int result1 = Add(5, 3);        // Calls first method
double result2 = Add(5.5, 3.2);  // Calls second method
int result3 = Add(5, 3, 2);      // Calls third method
Enter fullscreen mode Exit fullscreen mode

Optional Parameters and Named Arguments

Optional Parameters

Provide default values for parameters:

public static void CreateFile(string name, string extension = ".txt", bool overwrite = false)
{
    string fileName = $"{name}{extension}";
    Console.WriteLine($"Creating file: {fileName}, Overwrite: {overwrite}");
}

// Usage
CreateFile("document");                    // Uses default values
CreateFile("document", ".pdf");            // Overrides extension
CreateFile("document", ".pdf", true);      // Overrides both
Enter fullscreen mode Exit fullscreen mode

Named Arguments

Specify arguments by name rather than position:

CreateFile(name: "document", overwrite: true);
CreateFile(overwrite: true, name: "document"); // Order doesn't matter
Enter fullscreen mode Exit fullscreen mode

Expression-bodied Methods

Concise syntax for simple methods (C# 6+):

// Traditional syntax
public static int Square(int number)
{
    return number * number;
}

// Expression-bodied syntax
public static int Square(int number) => number * number;

// With void return type
public static void SayHello(string name) => Console.WriteLine($"Hello, {name}!");
Enter fullscreen mode Exit fullscreen mode

Local Functions (C# 7+)

Functions defined within other methods:

public static int CalculateFactorial(int number)
{
    // Local function
    int Factorial(int n)
    {
        if (n <= 1) return 1;
        return n * Factorial(n - 1);
    }

    return Factorial(number);
}
Enter fullscreen mode Exit fullscreen mode

Async Methods

Methods that support asynchronous operations:

public static async Task<string> GetDataAsync()
{
    // Simulate async operation
    await Task.Delay(1000);
    return "Data retrieved";
}

// Calling async method
string data = await GetDataAsync();
Enter fullscreen mode Exit fullscreen mode

Method Design Best Practices

1. Single Responsibility Principle

Each method should have one clear purpose:

// Good
public static double CalculateArea(double radius)
{
    return Math.PI * radius * radius;
}

public static void PrintArea(double area)
{
    Console.WriteLine($"The area is: {area:F2}");
}

// Avoid combining responsibilities
public static void CalculateAndPrintArea(double radius)
{
    double area = Math.PI * radius * radius;
    Console.WriteLine($"The area is: {area:F2}");
}
Enter fullscreen mode Exit fullscreen mode

2. Meaningful Names

// Good
public static bool IsPrimeNumber(int number)
{
    // Implementation
}

// Avoid
public static bool Check(int n)
{
    // Implementation
}
Enter fullscreen mode Exit fullscreen mode

3. Appropriate Method Length

Keep methods short and focused:

// Good - broken into smaller methods
public static void ProcessOrder(Order order)
{
    ValidateOrder(order);
    CalculateTotal(order);
    SaveOrder(order);
    SendConfirmation(order);
}

// Avoid - overly long method
public static void ProcessOrder(Order order)
{
    // 100+ lines of code doing everything
}
Enter fullscreen mode Exit fullscreen mode

4. Minimize Side Effects

Methods should ideally not modify external state:

// Good - pure function
public static int Add(int a, int b)
{
    return a + b; // No side effects
}

// Avoid when possible
public static int AddAndStore(int a, int b)
{
    int result = a + b;
    LastCalculation = result; // Side effect
    return result;
}
Enter fullscreen mode Exit fullscreen mode

Method Documentation

Use XML documentation comments for better code documentation:

/// <summary>
/// Calculates the area of a circle given its radius
/// </summary>
/// <param name="radius">The radius of the circle</param>
/// <returns>The area of the circle</returns>
/// <exception cref="ArgumentException">Thrown when radius is negative</exception>
public static double CalculateCircleArea(double radius)
{
    if (radius < 0)
        throw new ArgumentException("Radius cannot be negative", nameof(radius));

    return Math.PI * radius * radius;
}
Enter fullscreen mode Exit fullscreen mode

Common Method Patterns

1. Factory Methods

public static Person CreatePerson(string name, int age)
{
    return new Person
    {
        Name = name,
        Age = age,
        Id = Guid.NewGuid()
    };
}
Enter fullscreen mode Exit fullscreen mode

2. Validation Methods

public static bool IsValidEmail(string email)
{
    return email.Contains("@") && email.Contains(".");
}
Enter fullscreen mode Exit fullscreen mode

3. Helper Methods

public static string FormatCurrency(decimal amount)
{
    return amount.ToString("C");
}
Enter fullscreen mode Exit fullscreen mode

Error Handling in Methods

Returning Error Information

public static bool TryParseInt(string input, out int result)
{
    return int.TryParse(input, out result);
}

// Usage
if (TryParseInt("123", out int number))
{
    Console.WriteLine($"Parsed number: {number}");
}
else
{
    Console.WriteLine("Invalid number format");
}
Enter fullscreen mode Exit fullscreen mode

Exception Handling

public static double Divide(double dividend, double divisor)
{
    if (divisor == 0)
        throw new DivideByZeroException("Divisor cannot be zero");

    return dividend / divisor;
}
Enter fullscreen mode Exit fullscreen mode

Practical Examples

Example 1: Calculator Methods

public class Calculator
{
    public static double Add(double a, double b) => a + b;

    public static double Subtract(double a, double b) => a - b;

    public static double Multiply(double a, double b) => a * b;

    public static double Divide(double a, double b)
    {
        if (b == 0)
            throw new ArgumentException("Cannot divide by zero");
        return a / b;
    }

    public static double Power(double baseNumber, double exponent) => 
        Math.Pow(baseNumber, exponent);
}
Enter fullscreen mode Exit fullscreen mode

Example 2: String Processing Methods

public class StringProcessor
{
    public static string ReverseString(string input)
    {
        if (string.IsNullOrEmpty(input))
            return input;

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

    public static bool IsPalindrome(string input)
    {
        string cleanInput = input?.ToLower().Replace(" ", "") ?? "";
        string reversed = ReverseString(cleanInput);
        return cleanInput == reversed;
    }

    public static string[] SplitByComma(string input)
    {
        return input?.Split(',', StringSplitOptions.TrimEntries | 
            StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
    }
}
Enter fullscreen mode Exit fullscreen mode

Next Steps

Now that you understand methods, let's explore arrays and collections, which will allow you to work with groups of data efficiently.

Additional Resources

Top comments (0)