← Back to quizzesFree quiz

Fundamentals of C# Programming

Welcome to the Fundamentals of C# Programming course. This module is designed for beginners and intermediate developers who want to solidify their understanding of core C# concepts such as…

10 questions~5 min
Fundamentals of C# Programming — Qwi
0 / 10
Score: 0%
1

Which keyword must be used to declare a method that can be called without creating an instance of its class?

2

In C#, what is the effect of declaring a parameter with the keyword 'ref'?

3

Which of the following statements about C# structs is true?

4

What will be the output of the following code? int i = 5; Console.WriteLine(i == 5 ? "Five" : "Not Five");

5

Which interface must a class implement to be usable with a 'foreach' loop without explicitly providing an enumerator?

6

When overriding a virtual method in a derived class, which keyword must be used in the method declaration?

7

What is the purpose of the 'using' directive in a C# source file?

8

Which of the following correctly describes the behavior of the 'goto default;' statement inside a switch block?

9

What is the result of casting a double value 3.7 to an int using '(int) d' in C#?

10

Which access modifier makes a class member visible only to derived classes and classes within the same assembly?

Introduction to C# Fundamentals

Welcome to the Fundamentals of C# Programming course. This module is designed for beginners and intermediate developers who want to solidify their understanding of core C# concepts such as static members, reference parameters, structs, conditional operators, enumeration, method overriding, using directives, and switch‑case flow control. By the end of this lesson you will be able to write clean, efficient C# code and explain why each language feature behaves the way it does.

Static Members: Calling Methods Without an Instance

What is a static method?

A static method belongs to the class itself rather than to any particular object. Because it does not rely on instance data, you can invoke it directly using the class name:

public class MathHelper {
    public static int Add(int a, int b) => a + b;
}

int result = MathHelper.Add(3, 4); // No "new MathHelper()" required

The keyword static is the only one that enables this behavior. Other modifiers such as sealed, abstract, or public do not affect how a method is accessed.

  • When to use static methods: utility functions, factory methods, or any operation that does not need to maintain state.
  • Benefits: reduced memory footprint, easier testing, and clear intent that the method is independent of object state.

Reference Parameters with ref

Passing arguments by reference

In C#, parameters are passed by value by default. Adding the ref keyword changes this default behavior, allowing the method to modify the caller’s variable directly.

void Increment(ref int number) {
    number += 1; // Modifies the original variable
}

int count = 5;
Increment(ref count);
Console.WriteLine(count); // Outputs 6

Key points about ref:

  • The argument must be initialized before it is passed.
  • Both the caller and the callee see the same storage location, so changes are reflected immediately.
  • ref is different from out, which does not require the variable to be initialized but mandates assignment inside the method.

Understanding Structs

Value types vs. reference types

A struct in C# is a value type. This means that when you assign a struct to a new variable or pass it to a method, the entire value is copied, not just a reference.

struct Point {
    public int X;
    public int Y;
}

Point p1 = new Point { X = 1, Y = 2 };
Point p2 = p1; // Copies the values
p2.X = 10;
Console.WriteLine(p1.X); // Still 1

Because structs are stored on the stack (or inline within other objects), they are ideal for small, immutable data structures. Contrary to a common misconception, structs can contain methods, properties, and even interfaces; they simply cannot inherit from another struct or class.

  • When to choose a struct: lightweight data containers, points, colors, or any type that represents a single value.
  • When to avoid a struct: large objects, mutable data that requires polymorphism, or when you need inheritance.

Conditional (Ternary) Operator

Compact decision making

The ternary operator ?: provides a concise way to evaluate a Boolean expression and return one of two values.

int i = 5;
Console.WriteLine(i == 5 ? "Five" : "Not Five"); // Prints "Five"

In the example above, the expression i == 5 evaluates to true, so the first operand ("Five") is selected. This operator is especially useful for simple inline checks, but for more complex logic a full if/else block is recommended for readability.

Enumeration with IEnumerable

Making a class foreach‑compatible

To enable the foreach syntax, a class must implement the IEnumerable interface (or its generic counterpart IEnumerable<T>). This interface requires a GetEnumerator method that returns an IEnumerator.

public class SimpleCollection : IEnumerable {
    private int[] _items = {1, 2, 3};
    public IEnumerator GetEnumerator() => ((IEnumerable)_items).GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

foreach (var n in new SimpleCollection()) {
    Console.WriteLine(n);
}

Implementing IEnumerable abstracts the iteration logic, allowing the consumer to use foreach without worrying about the underlying data structure.

Method Overriding and the override Keyword

Polymorphism in derived classes

When a base class declares a method as virtual, a derived class can provide its own implementation using the override keyword. This tells the compiler that the method replaces the base implementation at runtime.

class Animal {
    public virtual void Speak() => Console.WriteLine("Animal sound");
}

class Dog : Animal {
    public override void Speak() => Console.WriteLine("Woof!");
}

Animal a = new Dog();
a.Speak(); // Outputs "Woof!"

Without override, the method would hide the base version (using the new keyword) rather than participate in polymorphic dispatch.

The using Directive

Simplifying namespace access

The using directive at the top of a C# file allows you to reference types without fully qualifying their namespace each time. For example:

using System.Text;

StringBuilder sb = new StringBuilder(); // No need for System.Text.StringBuilder

Note that this directive does **not** import DLLs or manage resource disposal; those tasks are handled by project references and the using statement block, respectively. Its primary purpose is to improve code readability and reduce typing.

Switch Statements and goto default

Control flow within a switch block

The goto default; statement explicitly transfers execution to the default case label inside the same switch. This can be useful when multiple case blocks share common fallback logic.

int value = 3;
switch (value) {
    case 1:
        Console.WriteLine("One");
        break;
    case 2:
        Console.WriteLine("Two");
        break;
    default:
        Console.WriteLine("Other");
        break;
    case 3:
        goto default; // Jumps to the default case
}

Using goto default does **not** cause a compilation error; it simply redirects the flow to the default label, ensuring consistent handling for specific cases that require the same outcome.

Summary and Best Practices

We have covered eight essential C# concepts:

  • Static methods – call without an instance.
  • ref parameters – pass arguments by reference.
  • Structs – value types that are copied on assignment.
  • Ternary operator – concise conditional expression.
  • IEnumerable – enables foreach loops.
  • override keyword – implements polymorphic behavior.
  • using directive – simplifies namespace usage.
  • goto default – transfers control to the default case in a switch.

Remember to apply each feature in the context where it adds clarity and performance. Overusing static members can lead to tightly coupled code, while misusing ref may make debugging harder. Choose structs for small, immutable data, and always implement IEnumerable when you want your collection to be iterable.

By mastering these fundamentals, you lay a strong foundation for more advanced topics such as async programming, LINQ, and design patterns in C#.