Chapter 5: Building Your Own Types with Object-Oriented Programming [Flashcarder]
What are the primary types of members that an object-oriented type in C# can have?
Fields to store data and methods to perform actions.
Which OOP concepts are used to combine related data and actions in a type?
Encapsulation
What is aggregation in object-oriented programming?
Aggregation refers to combining objects to form a new component. For example, a Person and a Car object can be aggregated when the Person becomes the Driver.
What is the difference between composition and aggregation in OOP?
Composition defines what an object is made of (e.g., a Car is composed of Wheels and an Engine), while aggregation refers to objects that can work together (e.g., a Person can drive a Car, but they are separate entities).
How is inheritance used in C#?
Inheritance allows a subclass to derive from a base class, inheriting all its functionality. The derived class can also extend or override certain functionality.
What is abstraction in OOP, and how is it implemented in C#?
Abstraction captures the core idea of an object and hides the details. It is implemented using abstract classes and interfaces.
What keyword is used to define an abstract class in C#?
The abstract keyword.
What is polymorphism in OOP?
Polymorphism allows a derived class to override an inherited method to provide custom behavior.
What are the keywords used in C# to define an object type?
class, record, and struct.
What C# keyword is used to restrict access to a class’s internal data?
private
What is the purpose of class library assemblies in .NET?
Class library assemblies group types together into easily deployable units, such as DLL files, to make code reusable across multiple projects.
How do you create a new class library in .NET using Visual Studio?
Select “Class Library” as the project template, name the project (e.g., PacktLibraryNetStandard2), and specify the solution folder (e.g., Chapter05).
What is the default target framework for class libraries created with the .NET 8 SDK?
The default target framework is .NET 8.0.
How can you modify a class library project to target .NET Standard 2.0 and use the C# 12 compiler?
Modify the <TargetFramework> to netstandard2.0, add <LangVersion>12</LangVersion>, and import the System.Console class statically for all C# files.</TargetFramework>
Why can’t all modern C# features be used in a .NET Standard 2.0 class library?
Some modern C# features, like default implementations in interfaces (C# 8) or the required keyword (C# 11), require newer .NET runtimes, such as .NET Standard 2.1 or .NET 7.
What is the recommended practice for supporting both modern and legacy .NET platforms in class libraries?
For modern features, use a .NET 8 class library. To support legacy platforms like .NET Framework and Xamarin, create a .NET Standard 2.0 class library and override the default C# 7 compiler to a newer version.
How do you compile a .NET class library in Visual Studio 2022?
Navigate to Build | Build <ProjectName> (e.g., Build PacktLibraryNetStandard2).</ProjectName>
How do you traditionally define a type such as a class in a namespace in C#?
Types are defined within curly braces inside a namespace block. For example:
~~~
namespace Packt.Shared
{
public class Person
{
}
}
~~~
What is a file-scoped namespace in C# and how is it different from traditional namespaces?
A file-scoped namespace simplifies code by ending the namespace declaration with a semicolon and removing the curly braces, allowing all types in the file to be part of the namespace without indentation. Example:
~~~
namespace Packt.Shared;
public class Person
{
}
~~~
Why is it considered good practice to put each type in its own code file or group types in the same namespace in a file?
It allows for the use of file-scoped namespaces, simplifying the structure and making the code easier to manage.
Why should classes be placed in a logically named namespace?
Logical namespaces, such as domain-specific ones (e.g., System.Numerics), help clarify the purpose of the types. For generic types without a domain, a more general namespace like Packt.Shared can be used.
What is the default access modifier for a class in C# if none is specified?
The default access modifier for a class is internal, meaning it is accessible only within its own assembly.
What does the public access modifier do when applied to a class in C#?
It allows the class to be accessible from other assemblies, making it available for use outside its own assembly.
What is the use of the file access modifier introduced in .NET 7?
The file access modifier restricts the visibility of a type to only the code file in which it is defined. This is rarely used but can be helpful in scenarios like source generators.
What is the recommended practice for using access modifiers on class members?
Always explicitly specify access modifiers, with public and internal being the most common. For clarity, avoid relying on default modifiers.
What are fields in C#?
Fields are used to store data and can be thought of as variables that belong to a type.
What are the three specialized categories of fields in C#?
The three specialized categories of fields are:
1. Constant: Data that never changes.
2. Read-only: Data that cannot change after the class is instantiated.
3. Event: Data that references methods to execute when an event occurs.
What is an example of a constant field in C#?
An example is byte.MaxValue, which is always 255.
What is a read-only field, and how is it different from a constant field?
A read-only field cannot change after instantiation but can be calculated or loaded at runtime, such as DateTime.UnixEpoch, which represents January 1, 1970.
What are methods in C# used for?
Methods are used to execute statements in a program.
What are the four specialized categories of methods in C#?
The four specialized categories are:
1. Constructor
2. Property
3. Indexer
4. Operator
What is the purpose of a constructor method in C#?
A constructor executes when the new keyword is used to instantiate a class, such as new DateTime(2023, 12, 25) to instantiate Christmas Day 2023.
What is the difference between a property and a field in C#?
A property is a specialized method that executes when data is accessed or modified, commonly used to encapsulate fields and control access to the data.
What is an indexer in C#?
An indexer allows data to be accessed using array-like syntax, such as name[0] to get the first character of the string name.
What is the role of an operator method in C#?
Operator methods define the behavior when applying operators like + or / to operands of a custom type.
How do you import a namespace to use a type in another project in C#?
You can import a namespace by adding a reference to the assembly containing the type and using the using statement to include the namespace at the top of the file.
How do you instantiate a class in C# using modern syntax?
You can instantiate a class using the new keyword. For example, Person bob = new(); uses C# 9 syntax to instantiate the Person class.
Why does the Person class in C# have a ToString method, even when the class is empty?
All C# classes inherit from System.Object, which provides the ToString method. The default implementation returns the full namespace and type name of the object.
What is the significance of inheriting from System.Object in C#?
All types in C# inherit from System.Object either directly or indirectly. It provides fundamental methods like ToString, Equals, and GetHashCode to all objects.
What is the purpose of explicitly inheriting from System.Object in C#?
Although not required, you can explicitly inherit from System.Object for clarity. For example, public class Person : object makes the inheritance explicit.
How can you avoid namespace conflicts when two namespaces contain types with the same name?
Use an alias for one of the namespaces to resolve conflicts. For example, using Tx = Texas; allows you to use Tx.Paris to differentiate between Texas.Paris and France.Paris.
How do you rename a type using an alias in C#?
You can rename a type using an alias with the using statement. For example, using Env = System.Environment; allows you to refer to System.Environment as Env throughout your code.
What are fields in C# and what are they used for?
Fields are used to store data in a class. They can be thought of as variables that belong to a type.
How would you define two public fields in a Person class to store a person’s name and birth date?
public class Person { public string? Name; // Can be null public DateTimeOffset Born; // Stores date, time, and UTC offset }
What is the difference between DateOnly, DateTime, and DateTimeOffset for storing date-related information?
- DateOnly: Stores only the date without time.
- DateTime: Stores both date and time, but it varies between local and UTC time.
- DateTimeOffset: Stores date, time, and UTC offset, accounting for time zones.
Since C# 8, how does the compiler handle reference types like string that can be null?
The compiler warns if a reference type could be null and potentially throw a NullReferenceException. You can use a ? to indicate a nullable type, removing the warning.
What are the six possible combinations of member access modifiers in C#?
- private: Accessible inside the type only (default).
- internal: Accessible inside the type and any type in the same assembly.
- protected: Accessible inside the type and any type that inherits from the type.
- public: Accessible everywhere.
- internal protected: Accessible inside the type, any type in the same assembly, and any type that inherits from the type.
- private protected: Accessible inside the type and any type that inherits from the type and is in the same assembly (C# 7.2 or later).
What is a good practice when applying access modifiers to fields in a class?
Always explicitly apply an access modifier, even when using the implicit private modifier. Fields should usually be private or protected, with public properties created to control access.
How do you set a person’s name and birth date using field values in C#?
You can set the values as follows:
~~~
bob.Name = “Bob Smith”;
bob.Born = new DateTimeOffset(1965, 12, 22, 16, 28, 0, TimeSpan.FromHours(-5));
~~~
How can you format a date in C# to display a long date format?
You can use the format specifier D for a long date format, e.g., WriteLine(“{0} was born on {1:D}.”, bob.Name, bob.Born);
What is object initializer syntax and how would you use it to instantiate a person named Alice in C#?
Object initializer syntax allows you to initialize an object in a concise way using curly braces. Example:
~~~
Person alice = new() {
Name = “Alice Jones”,
Born = new DateTimeOffset(1998, 3, 7, 16, 28, 0, TimeSpan.Zero)
};
~~~
What is a good practice when passing multiple arguments, particularly for complex types like DateTimeOffset?
Use named parameters to pass arguments, which makes the purpose of each argument clearer.
What is an enum type in C# and when would you use it?
An enum type is used to store a value that is one of a limited set of options, such as the ancient wonders of the world. For example:
~~~
public enum WondersOfTheAncientWorld {
GreatPyramidOfGiza,
HangingGardensOfBabylon,
StatueOfZeusAtOlympia,
// others
}
~~~
How do you set and output an enum value in C#?
You can set an enum field like this:
~~~
bob.FavoriteAncientWonder = WondersOfTheAncientWorld.StatueOfZeusAtOlympia;
WriteLine(“{0}’s favorite wonder is {1}.”, bob.Name, bob.FavoriteAncientWonder);
~~~
How are enum values stored internally in C#?
Enum values are stored as integers, with the values automatically starting at 0 unless specified otherwise. For example, the StatueOfZeusAtOlympia might be stored as 2.
How do you store multiple enum values in a single field in C#?
You can use the [Flags] attribute on the enum and combine values using the bitwise OR (|) operator. For example:
~~~
[Flags]
public enum WondersOfTheAncientWorld : byte {
GreatPyramidOfGiza = 1,
HangingGardensOfBabylon = 2,
MausoleumAtHalicarnassus = 16
}
bob.BucketList = WondersOfTheAncientWorld.HangingGardensOfBabylon
| WondersOfTheAncientWorld.MausoleumAtHalicarnassus;
~~~
Why is it useful to use the [Flags] attribute on an enum?
The [Flags] attribute allows an enum to represent a combination of values, storing multiple options in a single variable and displaying them as a comma-separated string instead of an integer.
How are enum values stored in memory when using the [Flags] attribute?
Each enum value is stored as a bit in memory. The values are designed to not overlap, using bitwise flags to combine them. For example:
* HangingGardensOfBabylon = 0b_0000_0010 (2)
* MausoleumAtHalicarnassus = 0b_0001_0000 (16) Combining these results in a value of 18.
What is a good practice when using enum types to store combinations of values?
Use an enum derived from byte if there are up to eight options, from ushort for up to 16 options, from uint for up to 32 options, and from ulong for up to 64 options.
How would you output a person’s bucket list of wonders using the [Flags] attribute?
After setting the bucket list values, you can output the combined enum values:WriteLine($"{bob.Name}'s bucket list is {bob.BucketList}.");
Example output:
“Bob Smith’s bucket list is HangingGardensOfBabylon, MausoleumAtHalicarnassus.”
What is an example of aggregation in C# using a collection?
Aggregation in C# can be represented by storing related instances of a class in a collection. For example, a Person class can store multiple Person instances representing children in a List<Person>, where the children are related but not part of the Person itself.</Person>
How do you define a field in C# to store multiple instances of a class?
Use a generic collection type like List<T> to store multiple instances of a class. Example:
`public List<Person> Children = new();`</Person></T>
What is the significance of initializing a List<T> in C# before adding items to it?</T>
Initializing a List<T> ensures the field is not null. If not initialized, attempting to use members like Add will result in a runtime exception.</T>
What are generics in C# and why are they used with collections?
Generics allow collections to be strongly typed, improving performance and correctness by enabling the compiler to know the exact type of objects stored in the collection. This prevents runtime errors and enhances type safety.
How do you add items to a generic List<T> in C#?</T>
You can add items to a List<T> using the Add method. For example:
`bob.Children.Add(new Person { Name = "Bella" });`</T>
What are the different versions of C# that allow adding children to a List<Person> in different ways?</Person>
- C# 1 or later: Person alfred = new Person();
- C# 3 or later: bob.Children.Add(new Person { Name = “Bella” });
- C# 9 or later: bob.Children.Add(new() { Name = “Zoe” });
What keyword is used in C# to create a constant field, and what is the restriction of such a field?
The const keyword is used to create a constant field in C#. The restriction is that the value of a constant field must be known at compile time and cannot be changed afterwards.
How is a constant field accessed in C#?
A constant field is accessed using the class name rather than the instance of the class.
Why might read-only fields be preferred over constant fields?
Read-only fields are preferred when the value can only be set at runtime and can be calculated or loaded from an external source. Unlike constants, they are not replaced by literal values at compile time and can reflect changes in future versions without recompiling.
What is the difference between a const field and a readonly field in C#?
A const field must be set at compile time and cannot change, whereas a readonly field can be set at runtime, typically in the constructor, and it cannot change after being initialized.
What happens if you attempt to change a readonly field after it has been set in C#?
It will result in a compile-time error, as readonly fields can only be set during initialization or in a constructor and cannot be modified thereafter.
What is the significance of the required modifier introduced in C# 11?
The required modifier ensures that certain fields or properties must be assigned a value when an instance of the class is created. It is enforced by the compiler to prevent the omission of these fields during instantiation.
What C# version and .NET target are required to use the required modifier?
The required modifier requires C# 11 and .NET 7 or later.
How would you instantiate a Book class with required fields in C# 11?
You can instantiate a Book class by specifying the required fields either through object initializer syntax or by using a constructor that takes the required parameters. For example:Book book = new() { Isbn = "978-1803237800", Title = "C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals" };
What is the purpose of a constructor in C#?
A constructor is a special method used to initialize fields of a class when an instance of that class is created using the new keyword.
How are read-only fields initialized in a constructor?
Read-only fields can be initialized within a constructor, allowing them to be set at runtime but preventing them from being modified later.
What does the following C# code do?public Person() { Name = "Unknown"; Instantiated = DateTime.Now; }
This constructor initializes the Name field to “Unknown” and the Instantiated field to the current date and time when a Person object is instantiated.
What happens if a class has multiple constructors?
Multiple constructors allow a class to be instantiated with different sets of initial values for its fields, providing flexibility for object creation.
How do you define a constructor that accepts parameters for initializing fields?
You define a constructor with parameters like this:public Person(string initialName, string homePlanet) { Name = initialName; HomePlanet = homePlanet; Instantiated = DateTime.Now; }
How would you instantiate a Person object using a constructor with parameters in C#?
You can instantiate it as follows:Person gunny = new(initialName: "Gunny", homePlanet: "Mars");
What is the output of the following C# code?Person blankPerson = new(); WriteLine($"{blankPerson.Name} of {blankPerson.HomePlanet} was created at {blankPerson.Instantiated:hh:mm:ss} on a {blankPerson.Instantiated:dddd}.");
The output will be:Unknown of Earth was created at [current time] on a [current day of the week].