Methods

Access rights

// static: is callable on a class even when no instance of the class has been created
public static void MyMethod()

// virtual: can be called or overridden in an inherited class
public virtual  void MyMethod()

// internal: access is limited within the current assembly
internal  void MyMethod()

//private: access is limited only within the same class
private  void MyMethod()

//public: access right from every class / assembly
public void MyMethod()

//protected: access is limited to the containing class or types derived from it
protected void MyMethod()

//protected internal: access is limited to the current assembly or types derived from the containing class.
protected internal void MyMethod()

Anonymous method

Anonymous methods provide a technique to pass a code block as a delegate parameter. They are methods with a body, but no name.

delegate int IntOp(int lhs, int rhs);
class Program
{
    static void Main(string[] args)
    {
        // C# 2.0 definition
        IntOp add = delegate(int lhs, int rhs)
        {
            return lhs + rhs;
        };

        // C# 3.0 definition
        IntOp mul = (lhs, rhs) =>
        {
            return lhs * rhs;
        };

        // C# 3.0 definition - shorthand
        IntOp sub = (lhs, rhs) => lhs - rhs;

        // Calling each method
        Console.WriteLine("2 + 3 = " + add(2, 3));
        Console.WriteLine("2 * 3 = " + mul(2, 3));
        Console.WriteLine("2 - 3 = " + sub(2, 3));
    }
}

Calling a Method

Calling a static method:

// Single argument
System.Console.WriteLine("Hello World");  

// Multiple arguments
string name = "User";
System.Console.WriteLine("Hello, {0}!", name);  

Calling a static method and storing its return value:

string input = System.Console.ReadLine();

Calling an instance method:

int x = 42;
// The instance method called here is Int32.ToString()
string xAsString = x.ToString();

Calling a generic method

// Assuming a method 'T[] CreateArray<T>(int size)'
DateTime[] dates = CreateArray<DateTime>(8);

Declaring a Method

Every method has a unique signature consisting of a accessor (public, private, ...) ,optional modifier (abstract), a name and if needed method parameters. Note, that the return type is not part of the signature. A method prototype looks like the following:

AccessModifier OptionalModifier ReturnType MethodName(InputParameters)
{
    //Method body
}

AccessModifier can be public, protected, pirvate or by default internal.

OptionalModifier can be static abstract virtual override new or sealed.

ReturnType can be void for no return or can be any type from the basic ones, as int to complex classes.

a Method may have some or no input parameters. to set parameters for a method, you should declare each one like normal variable declarations (like int a), and for more than one parameter you should use comma between them (like int a, int b).

Parameters may have default values. for this you should set a value for the parameter (like int a = 0). if a parameter has a default value, setting the input value is optional.

The following method example returns the sum of two integers:

private int Sum(int a, int b)
{
    return a + b;
} 

Default Parameters

You can use default parameters if you want to provide the option to leave out parameters:

static void SaySomething(string what = "ehh") {
    Console.WriteLine(what);
}  

static void Main() {
    // prints "hello"
    SaySomething("hello"); 
    // prints "ehh"
    SaySomething(); // The compiler compiles this as if we had typed SaySomething("ehh")
}

When you call such a method and omit a parameter for which a default value is provided, the compiler inserts that default value for you.

Keep in mind that parameters with default values need to be written after parameters without default values.

static void SaySomething(string say, string what = "ehh") {
        //Correct
        Console.WriteLine(say + what);
    }

static void SaySomethingElse(string what = "ehh", string say) {
        //Incorrect
        Console.WriteLine(say + what);
    }   

WARNING: Because it works that way, default values can be problematic in some cases. If you change the default value of a method parameter and don't recompile all callers of that method, those callers will still use the default value that was present when they were compiled, possibly causing inconsistencies.

Method overloading

Definition : When multiple methods with the same name are declared with different parameters, it is referred to as method overloading. Method overloading typically represents functions that are identical in their purpose but are written to accept different data types as their parameters.

Factors affecting

  • Number of Arguments
  • Type of arguments
  • Return Type**

Consider a method named Area that will perform calculation functions, which will accepts various arguments and return the result.

Example

public string Area(int value1)
{
    return String.Format("Area of Square is {0}", value1 * value1);
}

This method will accepts one argument and return a string, if we call the method with an integer(say 5) the output will be "Area of Square is 25".

public  double Area(double value1, double value2)
{
    return value1 * value2;
}

Similarly if we pass two double values to this method the output will be the product of the two values and are of type double. This can be used of multiplication as well as finding the Area of rectangles

public double Area(double value1)
{
    return 3.14 * Math.Pow(value1,2);
}

This can be used specially for finding the area of circle, which will accepts a double value(radius) and return another double value as its Area.

Each of these methods can be called normally without conflict - the compiler will examine the parameters of each method call to determine which version of Area needs to be used.

string squareArea = Area(2);
double rectangleArea = Area(32.0, 17.5);
double circleArea = Area(5.0); // all of these are valid and will compile.

**Note that return type alone cannot differentiate between two methods. For instance, if we had two definitions for Area that had the same parameters, like so:

public string Area(double width, double height) { ... }
public double Area(double width, double height) { ... }
// This will NOT compile. 

If we need to have our class use the same method names that return different values, we can remove the issues of ambiguity by implementing an interface and explicitly defining its usage.

public interface IAreaCalculatorString {
    
    public string Area(double width, double height);

}

public class AreaCalculator : IAreaCalculatorString {

    public string IAreaCalculatorString.Area(double width, double height) { ... } 
    // Note that the method call now explicitly says it will be used when called through
    // the IAreaCalculatorString interface, allowing us to resolve the ambiguity.
    public double Area(double width, double height) { ... }

Parameters and Arguments

A method can declare any number of parameters (in this example, i, s and o are the parameters):

static void DoSomething(int i, string s, object o) {
    Console.WriteLine(String.Format("i={0}, s={1}, o={2}", i, s, o));
}

Parameters can be used to pass values into a method, so that the method can work with them. This can be every kind of work like printing the values, or making modifications to the object referenced by a parameter, or storing the values.

When you call the method, you need to pass an actual value for every parameter. At this point, the values that you actually pass to the method call are called Arguments:

DoSomething(x, "hello", new object());

Return Types

A method can return either nothing (void), or a value of a specified type:

// If you don't want to return a value, use void as return type.
static void ReturnsNothing() { 
    Console.WriteLine("Returns nothing");
}

// If you want to return a value, you need to specify its type.
static string ReturnsHelloWorld() {
    return "Hello World";
}

If your method specifies a return value, the method must return a value. You do this using the return statement. Once a return statement has been reached, it returns the specified value and any code after it will not be run anymore (exceptions are finally blocks, which will still be executed before the method returns).

If your method returns nothing (void), you can still use the return statement without a value if you want to return from the method immediately. At the end of such a method, a return statement would be unnecessary though.

Examples of valid return statements:

return; 
return 0; 
return x * 2;
return Console.ReadLine();

Throwing an exception can end method execution without returning a value. Also, there are iterator blocks, where return values are generated by using the yield keyword, but those are special cases that will not be explained at this point.