Easy Learn C#

C# Methods Overview

Introduction to Methods

Methods are blocks of code that perform a specific task. They help organize code into reusable, modular components, making programs easier to understand, maintain, and debug. Methods are a fundamental building block of object-oriented programming in C#.

Key Method Concepts:

  • Methods encapsulate a sequence of statements that perform a specific task
  • They can accept input through parameters and return output through return values
  • Methods help avoid code duplication and improve code organization
  • In C#, methods must be declared within a class or struct
  • Methods can have different access modifiers to control their visibility

Method Declaration and Syntax

In C#, a method declaration consists of several parts that define its behavior and usage.

Basic Method Syntax:


[access_modifier] [modifiers] return_type MethodName([parameters])
{
    // Method body
    // Statements to execute
    
    [return statement];
}
                            

Method components:

  • Access modifier: Controls method visibility (public, private, protected, internal)
  • Modifiers: Optional keywords like static, virtual, abstract, override, etc.
  • Return type: The data type of the value the method returns (or void if it doesn't return a value)
  • Method name: Identifier that follows C# naming conventions (usually PascalCase)
  • Parameters: Input values the method can work with (optional)
  • Method body: Statements enclosed in curly braces that perform the method's work
  • Return statement: Specifies the value to return to the caller (if not void)

Method Examples:


// Simple method with no parameters or return value
public void ShowMessage()
{
    Console.WriteLine("Hello, World!");
}

// Method with parameters
public void DisplaySum(int a, int b)
{
    int sum = a + b;
    Console.WriteLine($"The sum of {a} and {b} is {sum}");
}

// Method with return value
public int Add(int a, int b)
{
    return a + b;
}

// Method with both parameters and return value
public bool IsEven(int number)
{
    return number % 2 == 0;
}

// Static method
public static double CalculateCircleArea(double radius)
{
    return Math.PI * radius * radius;
}

// Private method
private void LogError(string message)
{
    Console.WriteLine($"ERROR: {message}");
    // Save to log file, etc.
}
                            

Calling Methods

Methods are executed (or "called") by specifying the method name followed by parentheses, including any required argument values.

Method Call Syntax:


// For non-static methods, you call them on an instance of the class
ClassName objectName = new ClassName();
objectName.MethodName(arguments);

// For static methods, you call them directly on the class
ClassName.StaticMethodName(arguments);
                            

Method Call Examples:


public class Calculator
{
    // Instance method
    public int Add(int a, int b)
    {
        return a + b;
    }
    
    // Static method
    public static int Multiply(int a, int b)
    {
        return a * b;
    }
}

public class Program
{
    public static void Main()
    {
        // Calling instance methods
        Calculator calc = new Calculator();
        int sum = calc.Add(5, 3);  // sum = 8
        Console.WriteLine($"5 + 3 = {sum}");
        
        // Calling method and using result directly
        Console.WriteLine($"7 + 2 = {calc.Add(7, 2)}");  // 7 + 2 = 9
        
        // Calling static methods
        int product = Calculator.Multiply(4, 6);  // product = 24
        Console.WriteLine($"4 × 6 = {product}");
        
        // Calling method in control flow
        if (calc.Add(10, 5) > 10)
        {
            Console.WriteLine("The sum is greater than 10");
        }
        
        // Calling a method from another method
        DisplayResult(calc.Add(8, 4));
    }
    
    public static void DisplayResult(int result)
    {
        Console.WriteLine($"The result is: {result}");
    }
}
                            

Important points about method calls:

  • Instance methods require an object instance to be called
  • Static methods are called on the class itself
  • Arguments must match the parameter types and order
  • When a method returns a value, you can use it directly in expressions
  • Method calls can be nested (one method calling another)

Return Values and void

Methods can return a value to the caller using the return statement, or they can be declared as void if they don't need to return anything.

Return Type Examples:


// Method with no return value (void)
public void PrintMessage(string message)
{
    Console.WriteLine(message);
    // No return statement needed
}

// Method returning an integer
public int CalculateSum(int[] numbers)
{
    int sum = 0;
    foreach (int num in numbers)
    {
        sum += num;
    }
    return sum;  // Returns the result to the caller
}

// Method returning a boolean
public bool IsValidPassword(string password)
{
    if (string.IsNullOrEmpty(password))
    {
        return false;
    }
    
    if (password.Length < 8)
    {
        return false;
    }
    
    // More validation checks
    return true;  // Password passed all checks
}

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

// Method returning an object
public Person GetPersonById(int id)
{
    // Database lookup logic
    Person person = database.Find(id);
    return person;
}

// Method returning an array
public int[] GetEvenNumbers(int max)
{
    List result = new List();
    for (int i = 2; i <= max; i += 2)
    {
        result.Add(i);
    }
    return result.ToArray();
}
                            

Key points about return values:

  • The return statement immediately exits the method
  • Multiple return statements are allowed (but use with caution for readability)
  • The return type must match the declared method return type
  • Methods declared as void can use return; to exit early
  • You can return complex types like arrays, collections, and custom objects

Early Returns and Multiple Return Statements:


// Using multiple return statements for cleaner code (guard clauses)
public double CalculateDiscount(double price, int customerYears)
{
    // Input validation (guard clauses)
    if (price <= 0)
    {
        return 0;  // Early return for invalid price
    }
    
    if (customerYears < 0)
    {
        return 0;  // Early return for invalid customer years
    }
    
    // Business logic
    if (customerYears > 5)
    {
        return price * 0.2;  // 20% discount for loyal customers
    }
    else if (customerYears > 2)
    {
        return price * 0.1;  // 10% discount for regular customers
    }
    
    return price * 0.05;  // 5% discount for new customers
}

// Early return from a void method
public void ProcessOrder(Order order)
{
    if (order == null)
    {
        Console.WriteLine("Error: Order is null");
        return;  // Exit the method early
    }
    
    if (!order.IsValid)
    {
        Console.WriteLine("Error: Order is invalid");
        return;  // Exit the method early
    }
    
    // Process the valid order
    Console.WriteLine("Processing order...");
    // More processing logic
}
                            

Access Modifiers

Access modifiers control the visibility and accessibility of methods in your code.

Access Modifier Types:


// Public: accessible from anywhere
public void PublicMethod()
{
    Console.WriteLine("This method can be called from anywhere.");
}

// Private: accessible only within the containing class
private void PrivateMethod()
{
    Console.WriteLine("This method can only be called from within the same class.");
}

// Protected: accessible within the containing class and derived classes
protected void ProtectedMethod()
{
    Console.WriteLine("This method can be called from the same class or derived classes.");
}

// Internal: accessible within the same assembly
internal void InternalMethod()
{
    Console.WriteLine("This method can be called from anywhere in the same assembly.");
}

// Protected Internal: accessible within the same assembly or derived classes
protected internal void ProtectedInternalMethod()
{
    Console.WriteLine("This method can be called from the same assembly or derived classes.");
}

// Private Protected (C# 7.2+): accessible within the same class or derived classes in the same assembly
private protected void PrivateProtectedMethod()
{
    Console.WriteLine("This method can be called from the same class or derived classes in the same assembly.");
}
                            

Choosing the right access modifier:

Access Modifier Visibility Best Used For
public No restrictions APIs and methods that need to be called from outside the class
private Only within the class Internal helper methods and implementation details
protected Class and derived classes Methods that should be available to subclasses
internal Within the assembly Methods used across the project but not externally
protected internal Within assembly or derived classes Methods used by derived classes across assemblies

Static vs. Instance Methods

C# methods can be either static (class-level) or instance (object-level), with different usage patterns and purposes.

Static vs. Instance Methods:


public class Calculator
{
    // Instance fields
    private int operationCount;
    
    // Instance method - requires an instance of the class
    public int Add(int a, int b)
    {
        operationCount++;  // Can access instance fields
        return a + b;
    }
    
    // Instance method that uses the object's state
    public int GetOperationCount()
    {
        return operationCount;
    }
    
    // Static method - belongs to the class itself
    public static int Multiply(int a, int b)
    {
        // Cannot access instance fields or call instance methods directly
        // operationCount++;  // This would cause a compiler error
        return a * b;
    }
    
    // Static utility method
    public static bool IsPositive(int number)
    {
        return number > 0;
    }
}

// Usage:
public static void Main()
{
    // Instance methods require an object instance
    Calculator calc = new Calculator();
    int sum = calc.Add(5, 3);         // sum = 8
    int count = calc.GetOperationCount(); // count = 1
    
    // Static methods are called on the class itself
    int product = Calculator.Multiply(4, 5);  // product = 20
    bool isPos = Calculator.IsPositive(10);   // isPos = true
}
                            

Differences between static and instance methods:

Static Methods Instance Methods
Called on the class itself Called on an instance (object) of the class
Cannot access instance fields/methods Can access both instance and static members
Cannot use 'this' keyword Can use 'this' to refer to the current instance
Do not have access to object state Can work with object-specific data
Good for utility functions Good for operations that depend on object state

Method Organization and Best Practices

Well-organized methods lead to cleaner, more maintainable code. Following best practices helps improve code quality and readability.

Method Organization Best Practices:


// DO: Keep methods focused on a single task
public bool ValidateEmail(string email)
{
    if (string.IsNullOrEmpty(email))
        return false;
    
    // Check for @ symbol and proper domain format
    // ...
    
    return true;
}

// DON'T: Create methods that do too many things
public void ProcessUserInputDoTooMuch(string input)
{
    // Validate input
    // Parse input
    // Update database
    // Send notification email
    // Log activity
    // Update UI
    // ...
}

// DO: Break complex methods into smaller, focused methods
public void ProcessUserInput(string input)
{
    if (!ValidateInput(input))
        return;
    
    var data = ParseInput(input);
    SaveToDatabase(data);
    SendNotification(data);
    LogActivity("ProcessUserInput", data.Id);
}

// DO: Use descriptive, action-verb method names
public void SaveCustomer(Customer customer)
{
    // Implementation
}

// DON'T: Use vague method names
public void Process(Customer customer) // Too vague
{
    // Implementation
}

// DO: Group related methods together in your class
// All validation methods together, all data access methods together, etc.
                            

Method design principles:

  • Single Responsibility Principle: Each method should do only one thing
  • DRY (Don't Repeat Yourself): Extract common code into reusable methods
  • Method Length: Keep methods short (typically under 20-30 lines)
  • Parameter Count: Limit the number of parameters (ideally ≤ 3-4)
  • Naming: Use clear, descriptive names that indicate what the method does
  • Abstraction Level: Methods should operate at a single level of abstraction