Mastering C# Part 3.1 - Methods
Introduction, Method overloading, Method returning an object

Welcome back! Let’s dive deeper into one of the most important topics: Methods. If you’re new here or have missed the fundamentals, I recommend checking out some of the earlier blogs in the Mastering C# series, starting with Fundamentals. Let’s get started!
Methods
A method is a block of code that performs a specific task and may return a result. A method can also perform tasks without returning anything. In C#, methods are typically used to define behaviors of classes and objects.
Basic Syntax:
returnType MethodName(parameters)
{
// Method body (code to perform the task)
}
Return Type: The data type the method returns (e.g.,
int,string, orvoidif no return value).Method Name: The name of the method used to call it.
Parameters: Input values the method requires to perform its task. These are optional.
Method Body: The code inside the method that executes when it’s called.
Example of a Simple Method:
static void SayHello()
{
Console.WriteLine("Hello, World!");
}
- The method
SayHello()simply prints "Hello, World!" to the console. It doesn’t return anything, hence thevoidreturn type.
Method Overloading
Method Overloading allows defining multiple methods with the same name but different signatures. This is a form of polymorphism where methods can perform similar tasks but with different parameters.
How to overload methods:
Change the number of parameters.
Change the data types of the parameters.
Change the order of the parameters.
Example of Method Overloading:
using System;
class Program
{
// Method with one parameter
static void PrintMessage(string message)
{
Console.WriteLine(message);
}
// Overloaded method with two parameters
static void PrintMessage(string message, int times)
{
for (int i = 0; i < times; i++)
{
Console.WriteLine(message);
}
}
static void Main(string[] args)
{
PrintMessage("Hello!"); // Prints the message once
PrintMessage("Hello!", 3); // Prints the message 3 times
}
}
In the example above, PrintMessage is overloaded to accept either one parameter or two. The method's behavior changes based on the number of parameters passed.
Method Returning an Object
In C#, methods can return objects. This allows for more complex interactions between classes and their objects.
Example of a Method Returning an Object:
using System;
namespace Data_Types
{
class Triangle
{
private int Base, Height;
// Constructor to initialize Base and Height
public Triangle(int b, int h)
{
Base = b;
Height = h;
}
// Method to calculate Area
public int Area()
{
return (Base * Height) / 2;
}
// Method to display dimensions
public void Display()
{
Console.WriteLine($"Base of the triangle: {Base}, Height: {Height}");
}
// Method returning a new Triangle object
public Triangle Dimension(int d)
{
return new Triangle(Base * d, Height * d);
}
}
public class DataTypes
{
public static void Main(string[] args)
{
Triangle trng = new Triangle(3, 4);
trng.Display(); // Display original dimensions
Console.WriteLine("Area: " + trng.Area()); // Area calculation
// Create a new Triangle with doubled dimensions
Triangle t2 = trng.Dimension(2);
t2.Display(); // Display new dimensions
Console.WriteLine("Area: " + t2.Area()); // New area calculation
}
}
}
In this example, the Dimension method returns a new Triangle object, allowing dynamic manipulation of triangle properties. This is a common pattern used in real-world applications for returning complex objects.
Using Getter and Setter Methods
To control the access to the properties of a class, we use getter and setter methods (or properties). This ensures data encapsulation, preventing direct access to private fields.
Example with Getter and Setter Methods:
using System;
namespace Data_Types
{
class Triangle
{
private int Base { get; set; }
private int Height { get; set; }
// Constructor to initialize Base and Height
public Triangle(int b, int h)
{
Base = b;
Height = h;
}
// Method to calculate Area
public int Area()
{
return (Base * Height) / 2;
}
// Method to display dimensions
public void Display()
{
Console.WriteLine($"Base of the triangle: {Base}, Height: {Height}");
}
// Method to return a new Triangle object with modified dimensions
public Triangle Dimension(int d)
{
return new Triangle(Base * d, Height * d);
}
// Setter methods to change the values of Base and Height
public void SetBase(int b)
{
Base = b;
}
public void SetHeight(int h)
{
Height = h;
}
}
class DataTypes
{
public static void Main(string[] args)
{
Triangle trng = new Triangle(3, 4);
// Using setter methods to change the properties
trng.SetBase(4);
trng.SetHeight(5);
trng.Display(); // Display updated dimensions
Console.WriteLine("Area: " + trng.Area()); // Calculate updated area
// Create a new Triangle with doubled dimensions
Triangle t2 = trng.Dimension(2);
t2.Display(); // Display new dimensions
Console.WriteLine("Area: " + t2.Area()); // Calculate new area
}
}
}
In this example, the SetBase and SetHeight methods allow us to modify the private fields (Base and Height) of the Triangle class from outside the class, while maintaining control over the values being set.
C# Method Parameters Overview
In C#, methods can accept various types of parameters, each serving different purposes. Let's go over each type:
Named Parameters
Named parameters allow you to specify arguments for method parameters by name rather than by position. This enhances readability, especially when dealing with methods that have many parameters, and it allows you to provide arguments in any order.
Syntax:
MethodName(param1: value1, param2: value2, ...);
Example:
using System;
class Program
{
static void PrintMessage(string message, int count)
{
for (int i = 0; i < count; i++)
{
Console.WriteLine(message);
}
}
static void Main()
{
// Using named parameters to call the method
PrintMessage(message: "Hello, World!", count: 3);
}
}
In this example, the arguments are provided using their names (message and count), so the order doesn't matter.
Ref Parameters
A ref parameter allows a method to modify the value of an argument passed to it. For a parameter to be passed by ref, it must be initialized before being passed to the method.
Syntax:
public void MethodName(ref type param) { }
Example:
using System;
class Program
{
static void Increment(ref int number)
{
number++;
}
static void Main()
{
int x = 5;
Increment(ref x); // Passing by reference
Console.WriteLine(x); // Output: 6
}
}
Here, the value of x is modified within the Increment method due to the ref keyword.
Out Parameters
An out parameter is similar to ref, but it doesn’t require initialization before being passed to the method. The method must assign a value to the out parameter before the method ends.
Syntax:
public void MethodName(out type param) { }
Example
using System;
class Program
{
static void GetValues(out int x, out int y)
{
x = 10; // Must assign a value
y = 20; // Must assign a value
}
static void Main()
{
int a, b;
GetValues(out a, out b); // Using out parameters
Console.WriteLine($"a = {a}, b = {b}"); // Output: a = 10, b = 20
}
}
In this example, a and b are initialized within the GetValues method.
Default or Optional Parameters
Default parameters allow you to specify default values for parameters. If the caller doesn't provide a value for a parameter, the default value is used.
Syntax:
public void MethodName(int x = 10) { }
Example:
using System;
class Program
{
static void PrintMessage(string message, int repeatCount = 1)
{
for (int i = 0; i < repeatCount; i++)
{
Console.WriteLine(message);
}
}
static void Main()
{
PrintMessage("Hello"); // Default repeat count is used (1)
PrintMessage("World", 3); // Repeat count is explicitly set to 3
}
}
Here, if no value is provided for repeatCount, it defaults to 1.
Dynamic Parameters
A dynamic parameter allows you to pass parameters of any type at runtime. The parameter is evaluated at runtime and can hold any type of data.
Syntax:
public void MethodName(dynamic param) { }
Example:
using System;
class Program
{
static void Print(dynamic value)
{
Console.WriteLine($"Value: {value}");
}
static void Main()
{
Print(123); // Prints: Value: 123
Print("Hello World"); // Prints: Value: Hello World
Print(45.6); // Prints: Value: 45.6
}
}
Since dynamic is resolved at runtime, you can pass different types to the same method.
Value Parameters
Value parameters are the default in C#. When you pass a parameter to a method, its value is copied, and the method works with the copy. Changes made to the parameter inside the method do not affect the original argument.
Example:
using System;
class Program
{
static void Increment(int number)
{
number++;
}
static void Main()
{
int x = 5;
Increment(x); // Passing by value
Console.WriteLine(x); // Output: 5 (original value remains unchanged)
}
}
In this example, the value of x is passed to the Increment method, but changes made inside the method don’t affect x.
Params (Parameter Arrays)
The params keyword allows you to pass a variable number of arguments to a method. These arguments are passed as an array.
Syntax:
public void MethodName(params type[] paramsArray) { }
Example:
using System;
class Program
{
static void PrintNumbers(params int[] numbers)
{
foreach (var number in numbers)
{
Console.WriteLine(number);
}
}
static void Main()
{
PrintNumbers(1, 2, 3, 4, 5); // Passing a variable number of arguments
}
}
In this example, PrintNumbers accepts any number of integers, which are passed as an array.
Summary of C# Method Parameters:
Named Parameters: Allows parameters to be passed by name rather than position.
Ref Parameters: Parameters are passed by reference, allowing modifications inside the method.
Out Parameters: Parameters are passed by reference, but they must be assigned a value inside the method.
Default/Optional Parameters: Parameters that have default values if not provided by the caller.
Dynamic Parameters: Parameters that accept any type, determined at runtime.
Value Parameters: Default type, parameters are passed by value (copying the data).
Params: A variable-length parameter list, passed as an array.
These different parameter types provide flexibility in designing methods and making them more reusable and adaptable in various scenarios. Let me know if you need further explanations or examples!
Method Overriding
Method Overriding is a technique that allows the invoking of functions from another class (base class) in the derived class. Creating a method in the derived class with the same signature as a method in the base class is called as method overriding.
Overriding is a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes. When a method in a subclass has the same name, same parameters or signature and same return type(or sub-type) as a method in its super-class, then the method in the subclass is said to override the method in the super-class. Method overriding is one of the ways by which C# achieve Run Time Polymorphism(Dynamic Polymorphism).
The method that is overridden by an override declaration is called the overridden base method. An override method is a new implementation of a member that is inherited from a base class. The overridden base method must be virtual, abstract, or override.
We can override using
virtual
override
base method
Method overriding is possible only in derived classes. Because a method is overridden in the derived class from the base class.
A non-virtual or a static method can’t be overridden.
Both the override method and the virtual method must have the same access level modifier.
Example types
Example 1: Method Overriding without using virtual and override modifiers
using System; namespace Data_Types { class Book { public void read(){ Console.WriteLine("I am reading"); } } class Physics : Book { new public void read(){ Console.WriteLine("I am reading too but my dad is hidden"); } } class Data_Types { public static void Main(String[] args){ Book py = new Book(); py.read(); // output from base py = new Physics(); py.read(); // output from base } } } I am reading I am readingExample 2: Method overriding using virtual and override modifiers.
using System; namespace Data_Types { class Book { public virtual void read(){ Console.WriteLine("I am reading"); } } class Physics : Book { public override void read(){ Console.WriteLine("I am reading too but my dad is hidden"); } } class Data_Types { public static void Main(String[] args){ Book py = new Book(); py.read(); // output from base py = new Physics(); py.read(); // output from Physics } } } I am reading I am reading too but my dad is hiddenbase Keyword: This is used to access members of the base class from derived class. It basically used to access constructors and methods or functions of the base class. The base keyword cannot use within a static method. Base keyword specifies which constructor of the base class should be invoked while creating the instances of the derived class.
```csharp using System;
namespace Data_Types {
class Book {
public virtual void read(){ Console.WriteLine("I am reading"); } }
class Physics : Book { public override void read(){
base.read(); Console.WriteLine("I am reading too but my dad is hidden"); } } class Data_Types { public static void Main(String[] args){
Physics py = new Physics(); py.read(); // output from Physics abd book both } } }
**Use of *Base* keyword:**
* Call methods or functions of base class from derived class.
* Call constructor internally of base class at the time of *inheritance*.
```csharp
using System;
namespace Data_Types {
class Web {
string name = "Courses";
public virtual void showData(){
Console.WriteLine("Website name "+name);
}
}
class Stream : Web {
string name = "computer science";
public override void showData()
{
base.showData();
Console.WriteLine("About "+name);
}
}
class DataTypes {
static void Main(){
Stream st = new Stream();
// first it invokes the showData() of Base class
// later it invokes the showData() of child class
st.showData();
}
}
}
Example 4: How the base keyword specifies the calling of base-class constructor from derived class when derived class instances are created.
using System;
namespace Data_Types
{
class BaseClass
{
int n1, n2;
// constructor
public BaseClass()
{
Console.WriteLine("Default constructor pattern");
}
public BaseClass(int i, int j)
{
n1 = i;
n2 = j;
Console.WriteLine("Parameterized Constructor Invoked");
Console.WriteLine("Invoked Values are: " + n1 + " and " + n2);
}
}
class DerivedClass : BaseClass {
public DerivedClass(): base() {}
public DerivedClass(int i, int j): base(i, j){}
}
class DataTypes{
static void Main(){
// Invoke default constructor
DerivedClass d1 = new DerivedClass();
Console.WriteLine();
// Invoke parameterized constructor
DerivedClass d2 = new DerivedClass(10, 40);
}
}
}
Example 5: It shows how base keyword specifies the base-class constructor called from derived class and also calling of a method using the base keyword from the derived class.
using System;
namespace Data_Types
{
class BaseClass
{
public int n1, n2;
// constructor
public BaseClass()
{
Console.WriteLine("Default constructor pattern");
}
public BaseClass(int i, int j)
{
n1 = i;
n2 = j;
Console.WriteLine("Parameterized Constructor Invoked");
Console.WriteLine("Invoked Values are: " + n1 + " and " + n2);
}
public virtual void swap()
{
Console.WriteLine("Before swap num1 = {0} and num2 = {1} ", n1, n2);
int t = n1;
n1 = n2;
n2 = t;
Console.WriteLine("After swap num1 = {0} and num2 = {1} ", n1, n2);
}
}
class DerivedClass : BaseClass
{
public DerivedClass() : base() { }
public DerivedClass(int i, int j) : base(i, j) { }
public override void swap()
{
base.swap();
Console.WriteLine("Swapping back to original");
int t = n1;
n1 = n2;
n2 = t;
Console.WriteLine("Original value num1 {0} and num2{1} ", n1, n2);
}
}
class DataTypes
{
static void Main()
{
// Invoke default constructor
DerivedClass d1 = new DerivedClass();
Console.WriteLine();
// Invoke parameterized constructor
DerivedClass d2 = new DerivedClass(10, 40);
d2.swap();
}
}
}
Parameterized Constructor Invoked
Invoked Values are: 10 and 40
Before swap num1 = 10 and num2 = 40
After swap num1 = 40 and num2 = 10
Swapping back to original
Original value num1 10 and num240
Method Hiding
C# also provides a concept to hide the methods of the base class from derived class, this concept is known as Method Hiding. It is also known as Method Shadowing. In method hiding, you can hide the implementation of the methods of a base class from the derived class using the new keyword. Or in other words, in method hiding, you can redefine the method of the base class in the derived class by using the new keyword.
using System;
namespace Data_Types {
class Book {
public void read(){
Console.WriteLine("I am reading");
}
}
class Physics : Book {
public new void read(){
Console.WriteLine("I am reading too but my dad is hidden");
}
}
class Data_Types {
public static void Main(String[] args){
Physics py = new Physics();
py.read();
}
}
}
How to see the content of base class even at the case of method hiding
class Physics : Book {
public new void read(){
base.read();
Console.WriteLine("I am reading too but my dad is hidden");
}
}
By casting the derived class type to base class type
It will print the content of base class.
Physics py = new Physics();
((Book)py).read();
Optional Parameters in C#
Optional parameters in C# allow you to define method parameters with default values. If the caller does not provide a value for an optional parameter, the default value is used. This simplifies method calls when default values are sufficient for certain arguments.
Using default value
Method overloading
Using optional keyword
public void MethodName(type parameterName = defaultValue)
{
// Method body
}
Parameters with default values must appear at the end of the parameter list in the method signature.
This ensures that positional arguments can still be passed correctly for preceding parameters.
Basic Usage
using System;
class Program
{
static void PrintMessage(string message, int repeatCount = 1)
{
for (int i = 0; i < repeatCount; i++)
{
Console.WriteLine(message);
}
}
static void Main()
{
PrintMessage("Hello"); // Uses default repeatCount = 1
PrintMessage("World", 3); // Overrides repeatCount with 3
}
}
Multiple optional parameters
static void CreateAccount(string username, string email, bool isAdmin = false, int maxLogins = 5)
{
Console.WriteLine($"User: {username}, Email: {email}, IsAdmin: {isAdmin}, MaxLogins: {maxLogins}");
}
static void Main()
{
CreateAccount("JohnDoe", "john@example.com"); // Default values used
CreateAccount("AdminUser", "admin@example.com", true); // Override only isAdmin
CreateAccount("PowerUser", "power@example.com", true, 10); // Override all
}
