Basics of OOP in C#

studied byStudied by 5 people
5.0(1)
learn
LearnA personalized and smart learning plan
exam
Practice TestTake a test on your terms and definitions
spaced repetition
Spaced RepetitionScientifically backed study method
heart puzzle
Matching GameHow quick can you match all your cards?
flashcards
FlashcardsStudy terms and definitions

1 / 95

encourage image

There's no tags or description

Looks like no one added any tags here yet for you.

96 Terms

1

Why do we need Object-Oriented Programming (OOP)?

OOP helps in organizing complex code, promoting code reusability, making it easier to maintain and modify, and providing a clear structure through objects and classes.

New cards
2

What is procedural programming, and what problems can it cause?

Procedural programming is a programming paradigm that uses procedures or routines to perform tasks. It focuses on a sequence of steps or instructions that the program must execute, where the data and functions are separated.

Some problems procedural programming can cause include:

  • Maintenance difficulties: As code grows, it can become hard to manage, leading to challenges in debugging and updating.

  • Reusability issues: Since data and procedures are not encapsulated together, it can be harder to reuse code across different parts of a program or in different projects.

  • Scalability challenges: As the application grows, it can become complex and unwieldy, making it difficult to implement changes or new features.

New cards
3

What is an antipattern, and what is the spaghetti code antipattern?

An antipattern is a common response to a recurring problem that is usually ineffective and counterproductive. The spaghetti code antipattern refers to code that is poorly structured and tangled, making it difficult to follow, maintain, or debug. It often results from a lack of proper design and can hinder the development process.

New cards
4

What must be considered for high-quality code?

High-quality code should be:

  • Readable: Easy to understand and follow.

  • Maintainable: Simple to modify and extend over time.

  • Efficient: Performs well and optimally uses resources.

  • Robust: Handles errors gracefully and operates correctly under various conditions.

  • Scalable: Capable of growing in complexity without becoming difficult to manage.

New cards
5

What is Object-Oriented Programming (OOP)?

OOP is a programming paradigm centered around the concept of objects that encapsulate data and methods. It allows developers to create complex applications while maintaining readability and modifiability.

New cards
6

What are classes, objects, and instances?

In Object-Oriented Programming (OOP):

  • A class is a blueprint or template that defines the properties (attributes) and behaviors (methods) of a particular type of object.

  • An object is an individual instance of a class; it contains real values instead of variables and represents a specific item created from the class template.

  • An instance refers to a specific object created from a class in memory, embodying the structure and functionality defined by the class.

New cards
7

What are the benefits of Object-Oriented Programming (OOP)?

The benefits of OOP include:

  1. Improved Code Organization: OOP organizes code around objects and classes, which helps to create a more intuitive structure. This organization makes the code easier to read and manage by grouping related functionalities together.

  2. Code Reusability: Classes can be reused across different programs or within the same program, allowing developers to avoid code duplication. This not only saves time but also reduces the potential for errors, as shared code can be updated in one place and reflected everywhere the class is used.

  3. Enhanced Maintainability: Modifications to code are more straightforward within classes. If changes are required, they can often be made within a class without affecting other classes, minimizing the need for widespread changes and potential bugs.

  4. Encapsulation: OOP hides the internal state of an object, meaning that the internal implementation details are not exposed to the outside world. Only a controlled interface is provided for interaction, which improves security and prevents unintended interference with the object's state.

  5. Polymorphism: OOP allows for using a single interface to represent different data types or objects. This means that a function can process objects differently based on their class, enabling flexibility and the ability to extend functionality without modifying existing code.

New cards
8

What are the fundamental concepts of Object-Oriented Programming (OOP)?

OOP is based on four core concepts:

  • Encapsulation: Bundles data and methods into a class, controlling access and protecting internal state.

  • Inheritance: Allows subclasses to inherit properties from superclasses, promoting code reusability.

  • Polymorphism: Enables the same interface for different data types, allowing flexible method use across classes.

  • Abstraction: Hides complexity by exposing only essential parts,

New cards
9

What is the DateTime data type?

DateTime is a struct in C# used for representing a specific moment in time. It allows for the creation of instances that can be manipulated using various methods.

New cards
10

What is a constructor?

A constructor is a special function in a class that runs when you create an object from that class. Its main job is to set up the object's properties with specific values at the moment it's made, so the object is ready to use. For example:

var piDay = new DateTime(2025, 3, 14, 3, 14, 15);
//here we're passing in arguments that are taken into
//the constructor and set as values in the piDay object
//of type DateTime

New cards
11

What is abstraction?

Abstraction is a fundamental concept in Object-Oriented Programming (OOP) that involves simplifying complex systems by hiding unnecessary details while exposing only the essential features. It allows developers to focus on high-level interactions without needing to understand all the complex workings behind them. For example, when using a programming method (or a class, or a struct like DateTime), you may not need to know its internal implementation but can still leverage its functionality through a simple interface. Abstraction helps in reducing complexity and increasing efficiency when designing systems.

New cards
12

What are the benefits of hiding the implementation details from the users of a class?

Hiding the implementation details provides several benefits:

  1. Encapsulation: It separates the interface from the implementation, allowing changes to the implementation without affecting users.

  2. Security: Sensitive data and internal processes can be protected from unauthorized access and modification.

  3. Simplicity: Users interact with a simpler interface without needing to understand complex details, making it easier to use the class.

  4. Maintenance: It allows easier maintenance and updates since implementation can change without impacting code that relies on the class.

New cards
13

How can we define a class?

A class can be defined as a user-defined blueprint or template for creating objects in Object-Oriented Programming (OOP) with the help of the class keyword. It encapsulates shared properties (attributes) and behaviors (methods) of a specific type of object. Class names should conventionally start with a capital letter.

class Book
{
string title;
string author;
}

New cards
14

What are fields of a class?

Fields of a class are variables that hold data or state for an object. They are defined within the class and can be of various data types. Fields can be public (accessible from outside the class) or private (accessible only within the class), and they are typically used to represent the attributes or characteristics of the class's objects.

New cards
15

What are the default values of fields in a class?

In C#, the default values of fields are as follows:

  • Numeric types (e.g., int, double) default to 0.

  • Boolean type defaults to false.

  • Char type defaults to '\u0000' (null character).

  • Reference types (e.g., class instances) default to null.

  • For structs, each field gets its default value according to its type.

New cards
16

What is a default constructor?

A default constructor is a constructor that does not take any parameters. It is used to create an instance of a class with default values assigned to the fields. If no user-defined constructors are provided, many programming languages automatically supply a default constructor that initializes fields to their default values, as is the case with C#.

var myFavoriteBook = new Book(); //calling a default
//constructor

New cards
17

What is data hiding? Why should we use it?

Data hiding refers to the technique of limiting access to a class's fields and methods by making them non-public. This practice helps safeguard the integrity of the data by preventing external code from assigning invalid values to the fields.

New cards
18

What is a member of a class?

A member of a class is any variable, method, or property that is defined within the class. Members are used to define the state and behavior of the class. There are two main types of members:

  1. Fields (or Attributes): These are variables that hold data specific to an instance of the class.

  2. Methods: These are functions that define the behavior or actions that can be performed by instances of the class.

Additionally, classes can have properties, which are special methods that provide a flexible way to access and modify the values of fields. Members can also have different access modifiers (like public, private, or protected) that determine their visibility and accessibility from outside the class. Only necessary members should be made public to minimize risk.

New cards
19

What are access modifiers?

Access modifiers are keywords that define the visibility and accessibility of classes, methods, and members in programming.

New cards
20

What are the main access modifiers in C#?

The main access modifiers in C# are:

  1. public: Accessible from anywhere in the application.

  2. private: Accessible only within the defining class.

  3. protected: Accessible within the class and by derived classes.

  4. internal: Accessible only within the same assembly.

  5. protected internal: Accessible by any class in the same assembly or by derived classes in other assemblies.

These modifiers help enforce encapsulation and protect data integrity within a class.

New cards
21

What is the default access modifier for fields?

The default access modifier for fields in C# is private. If you do not explicitly specify an access modifier when declaring a field, it will be treated as private, meaning it can only be accessed within the class where it is defined.

New cards
22

How can we define a custom constructor? What is the constructor used for?

In C#, we can define a custom constructor by creating a method within a class that has the same name as the class itself and does not specify a return type. This method is used to initialize the object with specific values when it's created.

public class Book
{
public int Title;

// Custom constructor
public MyClass(string title)
{
Title = title;
}
}

New cards
23

How are constructors different from methods?

Constructors:

  • Initialize an object when it's created, setting up initial values or performing setup tasks

  • Have the exact same name as the class and no return type, not even void

  • Are called automatically when an object is instantiated using the new keyword

  • Do not have a return type

  • Are only called once when an object is created

Methods:

  • Perform specific actions or operations on an already created object

  • Can have any name (other than the class name) and must specify a return type or void

  • Are called explicitly on an object after it’s created

  • Have a defined return type or void if they don’t return anything

  • Can be called multiple times throughout the object’s lifetime

New cards
24

How should we name fields?

  • Avoid abbreviations and use meaningful names

  • For private fields, it's common to use _camelCase, starting with an underscore (e.g., _totalPrice, _name)

  • Use PascalCase for public static fields and ALL_CAPS for constants, with underscores separating words (e.g., InterestRate, MAX_SIZE)

public class Customer
{
private int _age;
private string _firstName;
public static int CustomerCount;
public const int MAX_NAME_LENGTH = 50;
}

New cards
25

Can C# code be defined outside a class?

No, in C# all code must be defined within a class, struct, or similar construct. Unlike some languages, C# does not allow executable code to exist outside of these structures, enforcing encapsulation and organization. Even the Main method must be within a class (typically named Program). This class-based structure aligns with C#’s object-oriented principles.

New cards
26

What are top-level statements?

Top-level statements in C# allow you to write code directly in a file without needing to explicitly define a Main method or a class. Introduced in C# 9, they simplify small programs or scripts by letting you start writing statements immediately at the file level.

New cards
27

How can we define a method inside a class?

In C#, you define a method inside a class by specifying an access modifier, return type, method name, and parameters (if any). Here's the structure:

public class MyClass
{
// Method definition
public void MyMethod()
{
// Method body
Console.WriteLine("Hello from MyMethod!");
}
}

To call the method, first you need to create an instance of MyClass and then use the dot notation, like this:

MyClass obj = new MyClass();
obj.MyMethod();

New cards
28

How should the methods be named in classes?

  • Use Pascal case (e.g., CalculateTotal, GetUserInfo)

  • Choose names that clearly describe what the method does (e.g., SaveData, FetchRecords)

  • Start method names with verbs to indicate actions (e.g., UpdateStatus, SendEmail)

  • Use full words instead of abbreviations unless they're well-known (e.g., use Initialize instead of Init)

  • Maintain a consistent naming pattern across your project to enhance readability.

New cards
29

How can we find out what are the default access modifiers in C#?

In C#, the default access modifiers depend on the type of member (class, method, property, etc.) you are defining.

  • Classes: default access modifier is internal. This means the class is accessible only within the same assembly unless specified otherwise.

  • Methods, Properties, and Fields: default access modifier is private. This means they are accessible only within the containing class.

  • Interfaces: default access modifier is public. All members of an interface are implicitly public.

  • Structs: default access modifier is internal, similar to classes.

New cards
30

What is encapsulation?

Encapsulation is a core principle of object-oriented programming that restricts direct access to certain components of an object and protects the object's internal state. It involves using access modifiers to hide data and expose only necessary methods. Its key points are:

  1. Data hiding - prevents unauthorized access and modification

  2. Public interfaces - controlling access to private data

  3. Improved maintenance - internal implementation of a class can be changed without affecting other parts of the code

  4. Enhanced security - external entities cannot directly manipulate the fields

New cards
31

How is encapsulation different from data hiding?

  • Encapsulation encompasses both the grouping of data and behavior and the control of access to that data.

  • Data hiding focuses specifically on restricting access to the internal data, promoting data integrity.

New cards
32

What is method overloading?

Method overloading refers to defining multiple methods within the same class that share the same name but have different parameter lists.

New cards
33

How can we properly use method overloading?

In order to use method overloading, the parameter list must differ in one or more of the following ways:

  • Number of parameters

  • Type of parameters

  • Order of parameters

The return type of the method together with the parameters list define the signature of the method - each method has to have a unique signature when using overloading.

public class Printer
{
// Method with one string parameter
public void Print(string text)
{
Console.WriteLine(text);
}

// Overloaded method with two string parameters
public void Print(string text, string prefix)
{
Console.WriteLine($"{prefix}: {text}");
}

// Overloaded method with an integer parameter
public void Print(int number)
{
Console.WriteLine($"Number: {number}");
}
}

New cards
34

How do we overload a constructor?

To overload a constructor in C#, you create multiple constructors within the same class that have the same name (the name of the class) but different parameter lists (different signature):

public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public int Year { get; set; }

// Constructor with no parameters (default constructor)
public Book()
{
Title = "Unknown";
Author = "Unknown";
Year = 0;
}

// Constructor with one parameter
public Book(string title)
{
Title = title;
Author = "Unknown";
Year = 0;
}

// Constructor with two parameters
public Book(string title, string author)
{
Title = title;
Author = author;
Year = 0;
}

// Constructor with three parameters
public Book(string title, string author, int year)
{
Title = title;
Author = author;
Year = year;
}
}

New cards
35

What is the advantage of using constructor overloading?

There are several advantages of using constructor overloading:

  1. Flexibility in object Initialization - initializing objects with different number of parameters

  2. Improved code readability and maintainability

  3. Avoiding redundant code - constructor chaining can be used to call one constructor from another, reducing code duplication

  4. Support for default and custom initialization

  5. Easier overloading for specific scenarios that otherwise would complicate the default constructor

New cards
36

How can we call one constructor from another one?

In C#, you can call one constructor from another within the same class using constructor chaining. This is done with the this keyword followed by the appropriate parameter list:

public class Vehicle
{
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }

// Constructor with three parameters
public Vehicle(string make, string model, int year)
{
Make = make;
Model = model;
Year = year;
}

// Constructor with two parameters, calling the main constructor
public Vehicle(string make, string model) : this(make, model, 0) // Calls the constructor with three parameters
{
}

// Constructor with one parameter, calling the main constructor
public Vehicle(string make) : this(make, "Unknown", 0) // Calls the constructor with three parameters
{
}

// Default constructor, calling the main constructor
public Vehicle() : this("Unknown", "Unknown", 0) // Calls the constructor with three parameters
{
}
}
  • The default constructor calls the constructor with three parameters and passes default values.

  • The constructor with one parameter sets the Make property and uses default values for Model and Year by calling the main constructor.

  • The constructor with two parameters calls the main constructor with a default Year of 0.

  • The main constructor (Vehicle(string make, string model, int year)) is the base constructor that performs the primary initialization.

New cards
37

What is an expression-bodied method?

An expression-bodied method in C# is a concise way to define a method using a single expression rather than a full block of code. This syntax allows you to create methods that return a value or perform an action without needing curly braces and a return statement when the method body consists of a single expression:

public class MathOperations
{
// Expression-bodied method to calculate the square of a number
public int Square(int x) => x * x;

// Expression-bodied method to check if a number is even
public bool IsEven(int x) => x % 2 == 0;
}

New cards
38

What is the difference between a statement and an expression?

  • An expression is a piece of code that evaluates to a value. Expressions can consist of variables, operators, method calls, or constants. They return a result but do not perform an action in the way statements do.

  • A statement is a complete unit of code that performs an action. Statements do not return a value on their own and typically control the flow of execution in a program. They may include expressions but also carry out actions such as declaring variables, controlling loops, or making decisions.

New cards
39

How can the this keyword be used to refer to the current instance of a class?

In C#, the this keyword is used within a class to refer to the current instance of that class. It helps differentiate between class instance members (like fields and methods) and parameters or other variables when they have the same name. One of the use cases is the following:

public class Person
{
private string name;
private int age;

// Constructor
public Person(string name, int age)
{
this.name = name; // 'this.name' refers to the instance variable
this.age = age; // 'this.age' refers to the instance variable
}

public void DisplayInfo()
{
Console.WriteLine($"Name: {this.name}, Age: {this.age}");
}
}

New cards
40

What are optional parameters? How do we use them?

Optional parameters in C# are parameters that can be omitted when calling a method. If an optional parameter is not provided, a default value is used instead. This feature allows methods to have fewer parameters and provides greater flexibility in method calls:

public class Calculator
{
// Method with one required parameter and two optional parameters
public int Add(int a, int b = 0, int c = 0)
{
return a + b + c;
}
}

// Usage
Calculator calculator = new Calculator();
Console.WriteLine(calculator.Add(5)); // Output: 5 (uses default values for b and c)
Console.WriteLine(calculator.Add(5, 10)); // Output: 15 (uses default value for c)
Console.WriteLine(calculator.Add(5, 10, 15)); // Output: 30 (all parameters provided)

New cards
41

What do we have to keep in mind about optional parameters?

  • Each optional parameter must have a default value defined. If the caller does not supply a value for that parameter, the default value will be used.

  • Optional parameters must be defined after any required parameters in the method signature.

  • The default value of an optional parameter must be compile-time constant

  • If methods/constructors have the same signature once we “remove” the optional parameters, the methods/constructors with no optional parameters are used

New cards
42

How can we validate constructor parameters?

We can validate constructor parameters by:

  1. Using conditional statements

  2. Using Assertions - for debugging purposes

  3. Using custom validation methods inside the constructor

  4. Using try-catch

New cards
43

What does nameof mean? What is it used for?

The nameof operator in C# is a compile-time operator that returns the name of a variable, type, or member as a string. It is primarily used for obtaining the name of a member (such as a property, method, or variable) without having to hard-code the name as a string, thereby providing a way to improve code maintainability and reduce the risk of errors.

New cards
44

What is the danger of having public fields?

  • Public fields expose the internal state of an object directly. This breaks the principle of encapsulation.

  • When fields are public, users of the class can change the field values directly, bypassing any logic that might be necessary for validating changes.

  • Public fields can be modified from outside the class, which can lead to inconsistent or invalid states. For example, if a class has a field representing an age, a user could set it to a negative value, leading to logical errors.

  • When external code accesses public fields, it becomes tightly coupled to the implementation of the class. If you later decide to change the internal representation or rename a field, it can break all code that relies on that field.

  • Maintaining and refactoring code becomes more difficult because changes to public fields can have widespread impacts on the codebase.

  • With public fields, you cannot easily introduce logic for field changes. For instance, if you need to log changes or trigger events when a field is updated, you must change the way the field is accessed, which can lead to breaking existing code.

  • If you need to add additional logic (like validation or event triggering) later, changing public fields to properties can be more cumbersome, requiring additional refactoring.

  • Public fields can lead to namespace pollution where many components are directly accessing and modifying the same fields. This can create conflicts and unintended side effects, especially in larger applications.

New cards
45

How can we prevent a field from being modified?

We can do that in multiple ways:

  • By using readonly fields

  • By using properties with private setters

  • By designing immutable classes

  • By using private fields with no public access

  • By encapsulating logic in methods

  • By using sealed classes and structs

New cards
46

What are immutable objects?

Immutable objects are objects whose state cannot be modified after they are created. Once an immutable object is instantiated, its fields or properties cannot change, ensuring that the data remains constant throughout its lifetime.

New cards
47

What is the difference between readonly and const?

  • A const field is a constant value that is set at compile time. It must be initialized at the time of declaration, and its value cannot change thereafter. const fields can be used in static contexts (e.g., static classes or methods) and can be accessed without creating an instance of the class.

  • A readonly field can be assigned either at the time of declaration or within the constructor of the class. Once assigned, its value cannot be changed. readonly fields are evaluated at runtime, allowing for more complex initialization logic, such as using parameters or results from methods.

New cards
48

What are the limitations of fields?

  1. Encapsulation issues: exposure of internal state and limited control over changes when using public fields

  2. Thread Safety concerns

  3. Difficulties in Refactoring: tight coupling and reduced flexibility

  4. Limited flexibility in Initialization: cannot use complex logic for initialization

  5. Lack of Inheritance behavior: no polymorphism

  6. Memory Management Considerations: increased memory usage and garbage collection issues in some cases

  7. Inability to implement complex logic: cannot trigger events or side effects

  8. Limited accessibility control: each field can only have one access modifier

New cards
49

Why do we need properties?

Properties play a crucial role in C# and object-oriented programming by providing a controlled way to manage access to an object's data, enhancing encapsulation, flexibility, and maintainability. They allow developers to implement logic for validation, notifications, and complex data handling while maintaining a clean and intuitive interface for users of the class. Using properties effectively leads to better-structured and more robust code.

New cards
50

What are properties?

Properties in C# are members of a class that provide a flexible way to access and modify private fields. They act as intermediaries, allowing you to control how values are read or written while encapsulating the internal state of an object. Properties can include:

  • Getters: To retrieve the value of a field.

  • Setters: To assign a value to a field, often including validation logic.

They enhance encapsulation, support data binding, and simplify syntax compared to using methods. Properties can also be read-only, write-only, or automatic, reducing boilerplate code.

public class Book
{
// Automatic property for Title
public string Title { get; set; }

// Automatic property for Author
public string Author { get; set; }

// Property for Pages with validation
private int pages;
public int Pages
{
get { return pages; }
set
{
if (value <= 0) throw new ArgumentException("Number of pages must be positive.");
pages = value;
}
}

// Read-only property for a summary
public string Summary => $"{Title} by {Author}, {Pages} pages";
}

// Usage
var book = new Book
{
Title = "1984",
Author = "George Orwell",
Pages = 328
};

Console.WriteLine(book.Summary); // Output: 1984 by George Orwell, 328 pages

New cards
51

What is a backing field of a property?

A backing field is a private field in a class that stores the actual data for a property. It acts as a storage location for the property's value and is typically used when the property has additional logic in its getter or setter. If the property has validation or other logic in the setter, the backing field is where the validated value is stored.

public class Person
{
private string name; // Backing field

// Property using the backing field
public string Name
{
get { return name; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Name cannot be empty.");
name = value; // Assigning to the backing field
}
}
}

// Usage
var person = new Person();
person.Name = "Alice"; // Sets the backing field
Console.WriteLine(person.Name); // Gets the value from the backing field

New cards
52

What are accessors?

Accessors are special methods in a class that provide controlled access to the properties or fields of an object. In C#, accessors typically refer to the get and set keywords used in properties. They define how the property values can be retrieved (getter) or assigned (setter).

New cards
53

What are the differences between fields and properties?

Fields:

  • Declared directly in a class

  • Can be public, private, protected, etc..

  • Are accessed directly

  • Have no built-in control over data assignment

  • Must be initialized directly or in a constructor

  • Are directly stored into an object

  • Are not inherently read-only or write-only

  • Are not suitable for data binding in UI frameworks

  • Are less encapsulated; direct access can lead to issues

Properties:

  • Provide controlled access to data

  • Can have separate access modifiers for getters and setters

  • Are accessed like fields but invoked through methods

  • Can include logic in getters and setters for validation or processing

  • Can use automatic properties or have custom logic for initialization

  • Their underlying data can be stored in a backing field or calculated at runtime

  • Can be defined as read-only, write-only, or both

  • Are commonly used in data binding scenarios with frameworks like WPF or ASP.NET

  • Provide better encapsulation, allowing control over how data is accessed and modified

New cards
54

When should we use fields, and when should we use properties?

  • Fields are best for simple internal data storage and performance-critical applications. They should always be private — if we want to expose a member of the class, we should do it with properties.

  • Properties are preferable for public interfaces, encapsulation, validation, and scenarios requiring flexibility or data binding.

New cards
55

What are object initializers?

Object initializers in C# provide a concise syntax for creating and initializing objects without explicitly calling a constructor. They allow you to set properties or fields of an object directly at the time of creation, enhancing code readability and maintainability.

public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

// Usage
var person = new Person
{
Name = "Alice",
Age = 30
};

Console.WriteLine($"Name: {person.Name}, Age: {person.Age}"); // Output: Name: Alice, Age: 30

Object initializers only work if we have public setters.

New cards
56

Do we have to provide all the properties when using object initializers?

No, you do not have to provide all properties when using object initializers in C#. You can initialize only the properties you want to set, and any properties that are not explicitly initialized will retain their default values.

public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string City { get; set; }
}

// Usage
var person = new Person
{
Name = "Alice",
Age = 30
// City is not initialized and will be null by default
};

Console.WriteLine($"Name: {person.Name}, Age: {person.Age}, City: {person.City ?? "Not specified"}");
// Output: Name: Alice, Age: 30, City: Not specified

New cards
57

What is the purpose of the init accessor?

The init accessor in C# is a special type of property accessor that allows you to set a property value during object initialization but prevents modifications after the object has been created. It was introduced in C# 9.0 as part of the enhancements for immutability and to support the concept of immutable objects.

public class Book
{
public string Title { get; init; } // Init-only property
public string Author { get; init; }
public int Pages { get; init; }
}

// Usage
var book = new Book
{
Title = "1984",
Author = "George Orwell",
Pages = 328
};

// book.Title = "Animal Farm"; // This line would cause a compilation error
Console.WriteLine($"{book.Title} by {book.Author}, {book.Pages} pages");
// Output: 1984 by George Orwell, 328 pages

New cards
58

What is the difference between creating an object with the help of the constructor, and by using an object initializer?

  • Constructors are useful when you need to pass all required parameters and potentially include validation logic during object creation.

  • Object initializers provide a more flexible and readable way to initialize properties, especially when you only want to set a few properties or when using immutable objects with init accessors.

New cards
59

What are computed properties?

Computed properties, also known as calculated properties, are properties in a class that do not store a value directly but instead compute their value based on other fields or properties within the class. They are typically read-only and allow you to encapsulate logic for deriving a value dynamically. Computed properties do not have a backing field; instead, their value is calculated on-the-fly when accessed.

public class Circle
{
public double Radius { get; set; }

// Computed property for Area
public double Area
{
get { return Math.PI * Radius * Radius; }
}

// Computed property for Circumference
public double Circumference
{
get { return 2 * Math.PI * Radius; }
}
}

// Usage
var circle = new Circle { Radius = 5 };
Console.WriteLine($"Area: {circle.Area}"); // Output: Area: 78.53981633974483
Console.WriteLine($"Circumference: {circle.Circumference}"); // Output: Circumference: 31.41592653589793

New cards
60

When should we use computed properties, and when parameterless methods?

Computed properties should be used for simple, lightweight calculations where the property represents data, while parameterless methods should be used for performance-heavy calculations to avoid repeated computation on every access. Methods are typically reserved for actions, while properties are for representing data.

New cards
61

What are static classes?

Static classes in C# are classes that cannot be instantiated and are used to contain static members only, such as methods, properties, or fields. They serve as a way to group related methods and variables without needing to create an object instance.

New cards
62

What are the main characteristics of static classes?

  • They are declared using the static keyword.

  • They cannot have constructors other than static constructors.

  • All their members must be static.

  • Are commonly used for utility or helper methods.

New cards
63

What are static methods?

Static methods in C# are methods that belong to a class rather than an instance of the class. This means they can be called on the class itself without needing to create an object of that class.

Key points about static methods:

  • Declared using the static keyword.

  • Can only access other static members (fields, properties, methods) within the class.

  • Commonly used for operations that do not require data from an instance of the class.

  • Called using the class name, e.g., ClassName.MethodName().

New cards
64

What are the limitations of static methods?

  1. No Instance Context: Static methods cannot access non-static (instance) members directly.

  2. Inheritance Restrictions: Static methods cannot be overridden or inherited.

  3. State Management: Static methods cannot maintain state across instances since they do not operate on an instance of the class.

  4. Thread Safety Concerns: If static methods modify static fields, special care must be taken to ensure thread safety.

  5. Limited Flexibility: Since static methods are tied to a specific class, they can’t be used with interfaces or easily mocked for unit testing.

New cards
65

When should we make methods static?

Methods should be static in C# when:

  1. There’s No Instance Dependency: The method does not need to access or modify instance variables or properties of a class. If a method performs operations that are not tied to an object instance, it is a good candidate for being static.

  2. Utility Functions: For methods that provide general functionality, such as mathematical calculations, string operations, or helper methods (e.g., Math.Sqrt() or DateTime.Now), static methods are ideal.

  3. Performance Considerations: Static methods may offer a slight performance advantage over instance methods because they do not require an instance of the class to be created.

  4. Global Access: If a method needs to be globally accessible without creating an instance of a class, making it static allows you to call it directly using the class name.

  5. No Overriding Required: When the method should not be overridden in derived classes, making it static prevents subclass modification and keeps its behavior consistent.

A good practice is to make all methods static if they’re not using any data of an instance.

New cards
66

Why are all const fields implicitly static?

All const fields in C# are implicitly static because they represent compile-time constants that are shared across all instances of a class. Here’s why:

  1. Compile-Time Evaluation: const fields are evaluated at compile time, meaning their values are fixed and known when the code is compiled. Since they don’t change, they don't require instance-level storage.

  2. Shared State: const fields belong to the type itself, not to any specific instance of the class. This is similar to static fields, which are also shared across all instances. Marking them implicitly static ensures that they are part of the class structure itself.

  3. Memory Efficiency: Since const fields are static, they are stored only once in the memory allocated for the class, rather than being replicated for each instance.

Due to these properties, const fields are implicitly static, even without explicitly specifying the static keyword.

New cards
67

What are static fields and static properties?

Static fields and static properties in C# are members of a class that are associated with the class itself rather than any instance of the class.

  • Static fields: Variables that are shared across all instances of a class. Declared using the static keyword. A single copy of the static field exists, and any changes to it reflect across all instances of the class. Typically used for values or data that need to be consistent across all instances, such as configuration settings or counters.

  • Static properties: Properties that are associated with the class itself, allowing access to get or set static data. Can include logic like instance properties but apply to the class level. Useful for encapsulating static fields, especially when some logic is needed in their getter or setter.

  • Both static fields and properties are accessed using the class name (e.g., Example.Counter, Example.Value).

  • Static properties are ideal for read-only or write-controlled access to static data, enhancing encapsulation.

New cards
68

What is a static constructor? What are its characteristics?

A static constructor in C# is a special type of constructor that initializes static fields or properties of a class. It is called automatically before any static members are accessed or any instance of the class is created.

  1. Declaration: It is defined using the static keyword and does not take any parameters.

    public class Example
    {
    static Example()
    {
    // Initialization logic for static members
    Console.WriteLine("Static constructor called");
    }
    }
  2. Automatic Invocation: The runtime calls the static constructor automatically. It runs only once per class, ensuring the static members are properly initialized.

  3. No Access Modifiers: Static constructors cannot have access modifiers (e.g., public, private) because they are only accessible to the runtime.

  4. Execution Timing: The static constructor is executed when the class is referenced for the first time, either through accessing a static member or creating an instance of the class.

  5. Use Case: Ideal for initializing static fields or performing setup tasks that only need to happen once for the class, such as loading configuration data or setting up a static resource.

public class Logger
{
public static readonly string LogFilePath;

static Logger()
{
// Initialize the static field
LogFilePath = "/path/to/log/file.txt";
Console.WriteLine("Logger static constructor executed");
}
}

New cards
69

Is using static fields and properties a good practice?

It can be, but there are some downfalls we need to be aware of, so it’s best to avoid them if and when possible.

New cards
70

What is the Single Responsibility Principle?

The Single Responsibility Principle (SRP) is a design principle that states a class should have only one reason to change, meaning it should have just one responsibility or purpose. By focusing on a single responsibility, classes become easier to maintain, test, and extend, as they aren't overloaded with multiple roles or functionalities.

New cards
71

What are SOLID principles?

The SOLID principles are a set of five design principles aimed at creating well-structured, maintainable, and scalable object-oriented software. They include:

  1. Single Responsibility Principle (SRP) - A class should have only one reason to change.

  2. Open/Closed Principle (OCP) - Software entities should be open for extension but closed for modification.

  3. Liskov Substitution Principle (LSP) - Subtypes must be substitutable for their base types without affecting correctness.

  4. Interface Segregation Principle (ISP) - Clients should not be forced to depend on interfaces they don’t use.

  5. Dependency Inversion Principle (DIP) - High-level modules should not depend on low-level modules; both should depend on abstractions.

New cards
72

How can we read from a text file in C#?

There are multiple ways we can read a text file in C#, all of them use the using System.IO namespace:

  1. Read All Lines: Reads all lines into a string array.

    string[] lines = File.ReadAllLines("path/to/file.txt");

  2. Read All Text: Reads the entire file content into a single string.

    string content = File.ReadAllText("path/to/file.txt");
  3. Read Line by Line: Using StreamReader to read each line.

    using (StreamReader reader = new StreamReader("path/to/file.txt"))
    {
    string line;
    while ((line = reader.ReadLine()) != null)
    {
    // Process the line
    }
    }

New cards
73

How can we write to a text file in C#?

There are multiple ways we can write to a text file in C#, all of them use the using System.IO namespace:

  1. Write All Lines: Writes an array of strings to a file.

    string[] lines = { "Line1", "Line2", "Line3" };
    File.WriteAllLines("path/to/file.txt", lines);
  2. Write All Text: Writes a single string to a file.

    string content = "Your content here";
    File.WriteAllText("path/to/file.txt", content);
  3. Append Text: Adds text to the end of a file.

    File.AppendAllText("path/to/file.txt", "New line of text\n");
  4. Write Line by Line: Using StreamWriter to write each line.

    using (StreamWriter writer = new StreamWriter("path/to/file.txt"))
    {
    writer.WriteLine("Line1");
    writer.WriteLine("Line2");
    }

New cards
74

How can we refactor a class that’s breaking the Single Responsibility Principle?

To refactor a class like this, we need to:

  1. Identify Responsibilities: Analyze the class to pinpoint each responsibility it currently handles.

  2. Separate Responsibilities into New Classes: For each identified responsibility, create a new class that will handle only that responsibility.

  3. Delegate Tasks: In the original class, replace the removed code with references or method calls to the new classes.

  4. Test the Refactored Classes: Ensure each new class works as expected on its own and that the refactored class still performs correctly through delegation.

New cards
75

What is a repository?

A repository is a design pattern often used in software development to encapsulate data access logic. It acts as an abstraction layer between the application and the data source (such as a database), allowing the application to perform data operations without directly interacting with the data storage mechanism.

New cards
76

What is the recommended order of methods in a class?

  1. Constructors should be the first type of methods defined in a class

  2. Methods using other methods should be defined first

  3. Public methods should be above protected, and protected should be above private

New cards
77

Can a public property that only has a getter be modified?

In some cases, yes it can. For example, if the property is a list, methods like Clear can still be called, and can modify the list.

New cards
78

What is the DRY principle?

The DRY principle stands for "Don't Repeat Yourself." It is a software development principle that emphasizes reducing repetition within code. By avoiding duplication, you make code more maintainable, readable, and less prone to errors. When a change is needed, it only has to be made in one place, reducing the risk of inconsistent updates across duplicated code.

New cards
79

When are code duplications not a bad thing?

While the DRY (Don't Repeat Yourself) principle is valuable in most situations, there are certain cases where code duplication is not necessarily a bad thing:

  1. Optimization for Readability or Simplicity: Sometimes, duplicating a small piece of code in different places may make the code clearer or easier to understand for developers. This can be particularly true if refactoring it into a shared method or function makes the code less intuitive or harder to follow.

  2. Performance Considerations: In some performance-critical situations, removing duplication by calling a shared method could add overhead (such as additional method calls or unnecessary computations).

  3. Low Complexity or Temporary Solutions: For small, one-off scripts or quick prototypes, duplication may be acceptable as the effort to remove it doesn't justify the gain in maintainability. If the code is expected to be short-lived or doesn’t have a long-term impact, the emphasis might be on speed over DRY adherence.

  4. Differences in Context: Code that seems similar but is contextually different should sometimes be duplicated rather than abstracted. Trying to combine them into one method can result in complex conditional logic, making the code harder to understand and maintain.

  5. Separation of Concerns (SoC): In certain cases, duplicating code may be necessary to maintain clear boundaries between concerns. Each module or function may have its own distinct responsibility, and copying a small amount of code could help maintain this separation rather than mixing responsibilities.

  6. When Duplication Serves as a Reminder or Documentation: In some cases, duplicating code can serve as an explicit reminder of certain logic being unique to each case. While this is not a common practice, it can be useful in specific domains where the uniqueness of each instance is important to highlight.

New cards
80

What are namespaces?

In C#, namespaces are used to organize and group related classes, interfaces, structs, enums, and other types together. They help avoid name conflicts, provide a clear structure for your code, and make large codebases easier to manage and understand. Types not placed in any namespace by default belong to the global namespace.

New cards
81

What are using directives?

In C#, a using directive is used to bring namespaces into scope, allowing you to access the types within those namespaces without needing to specify the full path every time. It simplifies the code by eliminating the need to repeatedly type long namespace paths.

New cards
82

Does importing a main namespace also imports all the sub-namespaces?

No, in C#, importing a main namespace does not automatically import its subnamespaces. Each namespace (and subnamespace) must be explicitly imported if you want to use types from it.

For example, if you add using System; at the top of your file, it will not automatically include subnamespaces like System.IO or System.Collections.Generic. You would need to explicitly add those using directives as well if you need types from them.

using System; // Imports the main System namespace
using System.IO; // Imports System.IO subnamespace
using System.Collections.Generic; // Imports System.Collections.Generic subnamespace

New cards
83

What are file-scoped namespaces?

File-scoped namespaces are a feature introduced in C# 10 that provides a more concise syntax for defining namespaces when all the contents of a file belong to a single namespace. With file-scoped namespaces, you can define a namespace without the usual curly braces, making the code cleaner and reducing indentation levels.

namespace MyApp.Models;

public class User
{
public string Name { get; set; }
}


//instead of

namespace MyApp.Models
{
public class User
{
public string Name { get; set; }
}
}

File-scoped namespaces apply to the entire file, so you can only have one file-scoped namespace per file.

New cards
84

What are global using directives?

Global using directives in C# allow you to specify using directives that are applied across an entire project, eliminating the need to repeat common using statements in every file. This feature, introduced in C# 10, is especially helpful for large projects where certain namespaces are used frequently across multiple files.

Best Practices

  • Use Sparingly: Only use global using directives for namespaces that are genuinely required across the majority of files, to avoid unnecessary namespace clutter.

  • Centralize in One File: To keep your project organized, place global using directives in a dedicated file (like GlobalUsings.cs) rather than scattering them across multiple files.

Limitations

  • Applies to Entire Project: Global using directives apply to all files in a project, so avoid using them for namespaces only needed in a few specific files, as it could lead to unintended conflicts.

New cards
85

How can we measure the time of code execution in C#?

In C#, you can measure the execution time of code using the Stopwatch class from the System.Diagnostics namespace. Stopwatch is a high-precision timer that provides an easy way to start, stop, and check elapsed time.

using System;
using System.Diagnostics;

public class Program
{
public static void Main()
{
// Start the stopwatch
Stopwatch stopwatch = Stopwatch.StartNew();

// Code to measure
PerformTask();

// Stop the stopwatch
stopwatch.Stop();

// Output the elapsed time
Console.WriteLine($"Elapsed Time: {stopwatch.ElapsedMilliseconds} ms");
}

private static void PerformTask()
{
// Simulate a task
System.Threading.Thread.Sleep(500);
}
}

New cards
86

How can we generate pseudorandom numbers?

With the use of the Random class:

Random random = new Random();
int number = random.Next(5, 15); // Range: 5 to 14

New cards
87

What are seed values for the pseudorandom numbers generator?

Seed values are values used for generating a sequence of numbers. If you create multiple instances of Random in quick succession, they may produce the same sequence of numbers because Random is seeded based on the system clock. To avoid this, reuse the same Random instance or specify a unique seed.

New cards
88

Is the Random class thread-safe?

Random is not thread-safe. For multithreaded scenarios, consider using ThreadLocal<Random> or System.Security.Cryptography.RandomNumberGenerator for secure random numbers.

New cards
89

Which Random class should we use for generating passwords and tokens?

For secure applications (e.g., generating passwords or tokens), use RandomNumberGenerator instead of Random, as it produces cryptographically secure random values.

New cards
90

What is a dependency of a class?

A dependency of a class is any external class, interface, or resource that the class requires to perform its functions. Dependencies are usually other objects or services that the class relies on to accomplish specific tasks or provide data. For example:

public class OrderProcessor
{
private readonly PaymentService _paymentService; //dependency of OrderProcessor
private readonly ILogger _logger; //dependency of OrderProcessor

public OrderProcessor(PaymentService paymentService, ILogger logger)
{
_paymentService = paymentService;
_logger = logger;
}

public void ProcessOrder(Order order)
{
_paymentService.ProcessPayment(order);
_logger.Log("Order processed.");
}
}

New cards
91

How are dependencies of a class used?

Dependencies of a class can be used in multiple ways:

  • Constructor Injection: Passing dependencies through the constructor.

  • Method Injection: Passing dependencies as parameters to a method.

  • Property Injection: Setting dependencies through properties.

New cards
92

What is the Magic Number antipattern? How can we avoid it?

The Magic Number antipattern refers to the use of hard-coded numeric values (and other data types, often with no obvious meaning) directly in the code, making it difficult to understand what these values represent or why they are used. This practice can lead to confusion, reduce code readability, and make maintenance and debugging more challenging.

New cards
93

What are enums?

Enums (short for enumerations) are a special type in C# that allows you to define a set of named constant values. Each value in an enum represents a specific, known option, making the code more readable and reducing the use of "magic numbers." Enums are particularly useful when you have a variable that can only take a limited, predefined set of values (which means they cannot contain any fields, properties, or methods). For example:

public enum OrderStatus
{
Pending,
Shipped,
Delivered,
Canceled
}

Can be used like this:

public class Order
{
public OrderStatus Status { get; set; }
}

Order order = new Order();
order.Status = OrderStatus.Shipped;

Console.WriteLine(order.Status); // Output: Shipped

New cards
94

What is the underlying type of enums?

By default, each value in an enum is assigned an integer starting from 0. You can explicitly set these values if needed:

public enum OrderStatus
{
Pending = 1,
Shipped = 2,
Delivered = 3,
Canceled = 4
}

New cards
95

What is casting?

Casting in C# is the process of converting a variable from one data type to another. It’s used when you need to treat a variable as a different type, either to access certain properties or methods, or to perform calculations that require a different data type. Casting can be explicit or implicit, depending on the types involved.

New cards
96

What is the ternary conditional operator? How do we use it?

The ternary conditional operator in C# is a shorthand way to perform a conditional check and return one of two values based on a condition. It’s often used to simplify if-else statements into a single line, making the code more concise. The syntax for the ternary operator is:

condition ? value_if_true : value_if_false;

For example:

int number = 10;
string result = (number > 5) ? "Greater than 5" : "5 or less";
Console.WriteLine(result); // Output: Greater than 5

New cards

Explore top notes

note Note
studied byStudied by 34 people
450 days ago
5.0(1)
note Note
studied byStudied by 32 people
850 days ago
5.0(1)
note Note
studied byStudied by 14 people
634 days ago
5.0(1)
note Note
studied byStudied by 2 people
140 days ago
5.0(1)
note Note
studied byStudied by 10 people
777 days ago
5.0(1)
note Note
studied byStudied by 35 people
868 days ago
5.0(1)
note Note
studied byStudied by 13 people
826 days ago
5.0(1)
note Note
studied byStudied by 13462 people
655 days ago
4.9(41)

Explore top flashcards

flashcards Flashcard (55)
studied byStudied by 6 people
712 days ago
5.0(1)
flashcards Flashcard (71)
studied byStudied by 1 person
99 days ago
5.0(2)
flashcards Flashcard (21)
studied byStudied by 2 people
268 days ago
5.0(1)
flashcards Flashcard (40)
studied byStudied by 5 people
663 days ago
5.0(1)
flashcards Flashcard (27)
studied byStudied by 29 people
338 days ago
5.0(1)
flashcards Flashcard (22)
studied byStudied by 1 person
669 days ago
4.0(1)
flashcards Flashcard (485)
studied byStudied by 43 people
267 days ago
5.0(1)
flashcards Flashcard (28)
studied byStudied by 25 people
407 days ago
5.0(1)
robot