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:
// 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)
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
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
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
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:
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:
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:
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:
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:
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:
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:
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:
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
// 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
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