C# 7.0 Flashcards

1
Q

What is the purpose of the readonly modifier when applied to a field in a class or struct?

A

It means the field’s value cannot be modified after the class’ constructor is called.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

When are initialisers run for fields and in what order are the initialisers run?

A

Field initialisers run before the object’s constructor runs, and they run in order of the corresponding field declarations from top to bottom.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What must always remain true of all method declarations in a class in order for those methods to coexist in the same class?

A

No two methods can have the same signature in the same class. That is, they cannot have both the same name and number of parameters in the same type order (names don’t matter), even if their return types are different.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

When can an expression-bodied member be used and what is an example of the syntax?

A

An expression-bodied member can be used when a method’s body comprises a single expression, e.g.

int doubleMe(int x) => 2 * x;

or

void printMe(string x) => Console.WriteLine(x);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Why would neither of the following pairs of methods compile?

void Foo(int x) { ... }
float Foo(int x) { ... }
void Bar(int[] x)
void Bar(params int[] x)
A
  1. The two methods named Foo have the same name and parameter type order, so the compiler cannot differentiate them when being called, even though their declarations have different return types.
  2. The two methods named Bar cannot coexist because the params modifier is not considered by the compiler (as, in the end, the params in Bar’s second declaration would be collected into an int[] and then be identical to Bar’s first declaration).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Which of the following pairs of method declarations can exist together, and why does introducing the third one cause a compile-time error in each case?

void Foo(int x) { ... }
float Foo(ref int x) { ... }
void Foo(out int x) { ... }
A
  1. The first and second can coexist as the ref parameter is considered a modifier for the parameter list, so it is still well-defined. Introducing the third method causes a compile-time error as the compiler does not distinguish ref and out parameters in the same position.
  2. The first and third methods can coexist as the out parameter is considered a modifier too. Introducing the second method causes a compile-time error for the same reason.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is the syntax for calling one overload of a class/struct constructor from a second overload of that constructor? Which of the two constructors is called first?

A

Using the ‘this’ keyword:

public class Foo
{
  public Foo(int x) { ... }
  public Foo(int x, int y) : this(x) { ... }
}

In this case, the FIRST constructor (the one called by ‘this’) is executed first.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Under what conditions are implicit parameterless constructors automatically defined by the compiler?

A

When, and only when, the class has no explicit constructors defined. As soon as one is defined, the compiler no longer generates one automatically.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What are deconstructors [C# 7.0] and how must they be declared in a class and used in a calling type?

A
  1. Deconstructors take fields/properties from a class and assign them to variables specified by the calling type.
  2. They must be named Deconstruct and must be have one or more ‘out’ parameters.
  3. When being called, they can be assigned to a tuple matching the same type order (or be implicitly typed), or by explicitly calling Deconstruct and specifying out parameters. Examples:

(var width, var height) = rectangle;
var (width, height) = rectangle; // Big brain syntax sugar
(width, height) = rectangle; // Assuming width, height already declared

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What is an object initializer and when is it called in relation to the constructor of a class when it is used?

A
  1. An object initialiser allow you to set fields in a class during the construction of an object, e.g.
var foo = new Foo { x = 1, y = 2 }; // Omit ( ) for default constructor
var foo2 = new Foo(x, y) { z = 3 };
  1. The fields that are set by an initialiser are set AFTER the constructor executes.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Where are two places the ‘this’ keyword CANNOT be used in a class?

A
  1. It cannot be used in any static members of a class
  2. It cannot be used in an expression passed to a constructor overload in the declaration of another overload, e.g.
public Foo(int x);
public Foo(int x, int y) : this(this.X); // Will not compile
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the GENERAL syntax for declaring a property with a backing field?

A

private decimal currentPrice; // Backing field

public decimal CurrentPrice
{
  get { return currentPrice; }
  set { currentPrice = value; } // value is an implicit argument name
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

How is an expression-bodied property [C# 6.0] interpreted by the C# compiler?

A

An expression-bodied property is interpreted as a read-only property. As an example:

public double NormalisedValue => rawValue / magnitude;

is equivalent to

public double NormalisedValue
{
get { return rawValue / magnitude };
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

How can expression-bodied properties be used to implement properties that are neither read nor write only?

A

Example

public int MyProperty
{
  get => myBackingField;
  set => myBackingField = value;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

How is an automatic property declared and how can its automatically-generated backing field be used?

A
  1. They are declared by specifying a property with a ‘get’ and/or ‘set’ with no implementation:

public int MyPubReadPrivateWriteProp { get; private set; }
public int MyReadOnlyProp { get; }
public int MyWriteOnlyProp { set; }

  1. You cannot refer to the automatically-generated backing field the compiler generates for an automatic property
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Will the following line of code compile?

public readonly int Maximum { get; } = 999;

A

Yes, as

  1. Properties can have initialisers in the same way that fields can
  2. Properties have the same readonly behaviour as fields
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Assuming MyType has an appropriate indexer implemented, will the following type compile and execute without any exceptions?

MyType myInst;
var myIndex = “foo”
Console.WriteLine(myInst?[myIndex])

A

Yes, as:

  1. The index can be any of any type, not just an integer
  2. Indexers can be called using the null-conditional, so using “?” on a null reference will simply result in the expression being null
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

How would an indexer be broadly implemented for a class?

A

By declaring a property named ‘this’, e.g.

public string this[int index]
{
  get { ... }
  set { ... }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

What the following class compile, why or why not?

public class MyClass
{
  public string this[int x] { get { ... } set { ...} }
  public string this[int x, int y] { get { ... } set { ...} }
  public string this[bool y] => ... 
}
A

Yes, as

  1. A class can have multiple indexers, as long as they have unique signatures for their index arguments
  2. An an indexer can accept more than one index argument
  3. Indexers can be expression bodied, in which case they are interpreted like read-only properties internally
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

What are two ways that a constant is different from a static readonly field?

A
  1. Constants must be initialised in their declaration, unlike readonly properties that can be initialised in a static constructor
  2. The value a constant takes must itself be a constant expression (as it is evaluated at compile time)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

What constraints apply to static constructors for a type?

A
  1. There must be only one static constructor
  2. The constructor must be explicitly declared ‘static’ and have the same name as the type
  3. The constructor cannot accept any parameters
22
Q

When are static field initialisers run with AND without a static constructor present?

A

If no static constructor is present, the fields will be initialised any time between the start of the runtime and the first time the type is used (through instantiation of a non-static type with a static field or through accessing any of the static fields of a given type).

If a static constructor is present, the static field initialisers will execute just before the static constructor is executed at the start of runtime.

23
Q

What are two constraints that apply to a class that is marked static?

A
  1. The class must only contain static members

2. The class cannot serve as the base class for any other class

24
Q

When is a class finalizer run and what is the syntax for declaring one?

A

A finaliser executes just before an object is garbage collected, and is technically an override for the Finalize() method of the Object class from which all reference types inherit.

The syntax is to use the name of the class preceded by a tilde:

~MyClass() => Console.WriteLine(“It can be expression bodied too”);

25
Q

How would a partial method be declared between two parts of a partial class?

A

In one partial class, provide the declaration of the method:

public partial class MyClass
{
  public partial int SquareMe(int x);
}

In a second partial class, provide the implementation:

public partial class MyClass
{
  public partial int SquareMe(int x)
  {
     return x * x;
  }
}
26
Q

What does the nameof operator [C# 6.0] do and what is its main purpose?

A
  1. The nameof() operator returns the name of whichever member is passed to it

nameof (StringBuilder.Length); // returns “Length”

  1. It is beneficial to use this because if referring to certain named values that could change, this adds a way to update references to that named value where it is used elsewhere
27
Q

What is the general definition of polymorphism in reference to inheritance in C#?

A

If you have some reference x of type X, then x can be assigned a value of type Y if and only if Y is a subclass (a derived class) of X. The converse is not true, in that a reference y of type Y can never accept a value of its superclass (base class) X.

28
Q

What are upcasting and downcasting in relation to inheritance in C#, and what is the primary difference between how they are treated?

A
  1. Any object reference can be implicitly upcast to any of any of its base types (as in the definition of polymorphic behaviour)
  2. An object reference can be cast to one of its derived types, but the cast must be explicit and only succeeds if the reference is actually of the target type.
29
Q

Under what conditions will the following code compile?

A a = new A();
B b = a;
A aa = (A)b;
A

This would only compile if A were a subclass of B.

  1. The implicit upcast would only compile if A were a subclass of B.
  2. The explicit downcast from a reference of type B to a reference of type A would only succeed if b actually points to an instance of type A through a reference conversion (which occurs during an implicit up-cast)
30
Q

What is the difference between using ‘as’ to downcast a reference as opposed to doing an explicit downcast?

A

An explicit downcast throws an InvalidCastException if it fails, where using the ‘as’ operator returns null if the downcast did not succeed.

31
Q

What is the equivalent syntax for the following statements?

if (a is Stock s)
Console.WriteLine(s.SharesOwned);

A

Stock s;

if (a is Stock)
{
    s = (Stock) a;
    Console.WriteLine(s.SharesOwned);
}
32
Q

What is the purpose of declaring a class member virtual and which types of members can be virtual?

A
  1. You mark a member as virtual if you expect a derived class to override that member in its own definition
  2. Methods, properties, indexers and events can be marked as virtual
33
Q

What does the following code print?

House mansion = new House { Name = “McMansion”, Mortgage = 250000 };
Asset a = mansion;
Console.WriteLine(a.Liability);
Console.WriteLine(mansion.Liability);

public class House : Asset
{
   public int Mortgage { get; set; }
   public override int Liability => Mortgage;
}
A

Both print 250000 as House overrides the Liability property of Asset, so even if an object of type Mansion is upcast to a type Asset, the override from the derived class will be referenced.

34
Q

What is the distinction between declaring a member abstract or virtual?

A
  1. Virtual members can be overridden by derived classes, but must be fully-defined in the base class.
  2. Abstract members define methods in an abstract class that must be defined in a derived class, but abstract methods do not provide an implementation of their own (and don’t need to, as abstract classes cannot be directly instantiated)
35
Q

What are two cases in which you would use the ‘base’ keyword?

A
  1. When you need to access the base class implementation of a virtual method (or any member of the derived type, in a similar manner to the ‘this’ reference) that has been overridden in the derived class.
  2. When you need to access a base class constructor from a derived class.
36
Q

What is the general syntax for calling a base class constructor from a derived class’ constructor and why would you want to do this?

A
public class Subclass : Baseclass
{
    public Subclass(int x) : base(x) { }
}

The derived class does not inherit the constructors from the base class, so any like constructors must be ‘redefined’ in the derived class, which can access the constructors from the base class.

37
Q

What are the ways you would get the type information of an object reference and get the type information of a class reference?

A
  1. For an object reference o, o.GetType() will get the System.Type represening that object
  2. For a class MyClass, typeof(MyClass) will return the System.Type information for MyClass
38
Q

What are the main differences between a struct and a class?

A
  1. Structs are value types, not reference types
  2. Structs do not support inheritance or virtual/protected members
  3. Structs cannot have parameterless constructors,
  4. Structs cannot have field initialisers
  5. Structs cannot have finalisers
39
Q

What are three reasons the following code will not compile?

public struct Point
{
int x = 1;
int y;

    public Point() { }
    public Point(int x) { this.x = x; }
}
A
  1. Structs cannot have field initialisers, so x cannot be initialised unless it is done in a constructor
  2. Structs cannot define a default parameterless constructor as one implicitly exist to zero all the fields
  3. A custom constructor must set all fields to some value when it executes, so that it matches the behaviour or the default constructor to initialise all values
40
Q

What is the accessibility level of the below class and its members?

class MyClass
{
    int x;
    void Foo();
}
A
  1. MyClass is internal by default

2. Foo and x are private by default

41
Q

What are the differences between an interface and a class?

A
  1. All members of an interface are inherently public and abstract
  2. Interfaces can only contain properties, methods, indexers and events, the member types that can be marked abstract in a class
  3. A class can implement multiple interfaces, but may only extend one class
42
Q

When would an explicit interface implementation be required?

A

When a class implements two interfaces that have conflicting signatures, one of the methods must be implemented explicitly, e.g.

interface IFirst { void Foo(); }
interface ISecond { int Foo(); }

A class implementing these two interfaces would need to explicitly implement Foo from either IFirst or ISecond, as below:

public class MyClass : IFirst, ISecond
{
   public void Foo()  { }
   public int ISecond.Foo() { return 0; }
}

MyClass would need to be cast to ISecond in order to access the explicit implementation.

43
Q

By default, which inheritance modifier is applied to implicit implementations of interface members and what consequences that have for classes that implement that interface?

A

By default, implicit implementations are marked as sealed, so the class that implements an interface method implicitly must mark its implementation as virtual, then subclasses mark their implementation as override.

44
Q

What is interface reimplementation and in which case is it specifically required?

A
  1. Assuming a class BaseClass implements an interface IBase, if a class DerivedClass extends BaseClass and implements IBase, it will reimplement methods from BaseClass, meaning aeny calls to IBase’s methods will use the implementation from DerivedClass
  2. Explicitly-implemented interface methods cannot be marked as virtual (hence are always sealed), so any derived class would need to reimplement those sealed methods
45
Q

What is the default type and value for the members of an Enum?

A
  1. Members are implicitly of type int

2. The value starts at 0 for the first ordered value and increments by 1 for subsequent values

46
Q

How would you declare a flags enum and assign it a value?

A
  1. Declare the enum and add the [Flags] attribute, then explicitly define the member values in powers of two:
[Flags]
public enum Alignment : byte
{
    None = 0,
    Left = 1,
    Right = 2,
    Top = 4,
    Bottom = 8
}
  1. To use the enum, use the bitwise operators when assigning the value:

Alignment bottomLeft = Alignment.Bottom | Alignment.Left

bool isBottomAligned = bottomLeft & Alignment.Bottom;

47
Q

Will the following code compile?

public enum Border { Left, Right, Top, Bottom }

Border myBorder = (Border) 6;

A
  1. This code compiles, even though the integer value 6 is out of bounds of the enum
  2. The static method Enum.IsDefined() will return true if the value an enum type has is in bounds, except if it is a flags enum.
48
Q

Which types can be nested and what and what key differences are there between nested types and top-level types?

A
  1. All types can be nested (delegates, interfaces, classes, events and structs)
  2. Nested types can be public, private, protected or internal, while non-nested types are either public or internal
  3. Nested types are private by default, rather than internal
  4. Nested types can access members from the enclosing types (while there isn’t really a logical equivalent for non-nested types)
49
Q

What is an open type versus a closed type and what is always true of all types during runtime?

A
  1. An open type is one that specifies a generic type parameter in its definition, e.g. Stack
  2. A closed type is one that specifies explicit type arguments when it is consumed, e.g. creating a Stack
  3. At runtime, all types must be closed. If the compiler cannot resolve an open type parameter to an explicit type argument at compile time, the compiler generates an error
50
Q

When is a method considered generic?

A

A method is only generic if it introduces a generic type parameter that was not introduced in the enclosing type e.g.

public class MyGenericType
{
    public void MyGenericMethod<u>() { }
}

In the above example, as T and U are different type parameters, MyGenericMethod would be generic. If that method took the same generic type parameter T as the enclosing type, that method would not be considered generic in that context.</u>