4. Advanced C# || C# 10 Flashcards

1
Q

What is a delegate?

A

A delegate is an object that knows how to call a method.
Delegates type specifically defines methods return type and its parameters types.

delegate int Transformer (int x);
Now this Transformer is compatible with any method which return type is int and has one parameter of type int. Such as:
int Square (int x) { return x*x;}

Also Transformer now can be used as a type, and following is possible:
Transformer t = Square;
var x = t(3); // 9;

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

What is a higher-order function?

A

A function that takes a function as a parameter. Example would be a delegate as param or return type

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

What is a multicast delegate?

A

it a delegate that can reference a list of target methods.
~~~
SomeDelegate d = SomeMethod1;
d += SomeMethod2;
~~~
Invoking d will now invoke SomeMethod1 and SomeMethod2 in the same order they were added.
Note: delegates are immutable so every time the += or -= are performed, new delegate is created an assigned to the same variable.

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

What are Func and Action delegates?

A

These are generic delegates that work for methods of any return type and any number of arguments.
In and out annotations indicate variance:
delegate TResult Func <out TResult>();
delegate TResult Func <in T, out TResult> (T arg);
Difference between Func and Action delegates is that Action delegate does not have a return type

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

Since we are able to implement the same delegate functionality with interface, which is better and why?

A

Delegates should be used for simplier syntax.
Also, for interface to be able to implement this these conditions should be true:
- The interface defines only a single method
- Multicast capability is needed
- The subscriber needs to implement the interface multiple times

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

When multicast delegates are considered equal?

A

When they reference the same methods in the same order

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

What is a broadcaster and subscriber?

A

Broadcaster is a type that contains a delegate field. The broadcaster decides when to broadcast by invoking the delegate

The subscribers are the method target recipients. A subscriber does not interfere with other subscribers.

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

What are events?

A

An event is a construct that exposes just the subset of delegate features required for the subscriber/broadcaster model. The main purpose of events is to prevent subscribers from interfering with one another.
Simpliest way to declare an event is to put the ‘event’ keyword in front of a delegate member:

// Delegate definition
public delegate void MyDelegate(decimal x, decimal y);
// Event declaration
public event MyDelegate MyEvent;

For the event to be able to call any method, it needs to be added += or removed -= from the event’s method list. Keep in mind that those methods should still keep the suggested signature (following how delegates work).
The event will be triggered :
MyEvent (1.1m, 2.2m);
Then all subscribed methods will be called in order they subscribed

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

Compare multicast delegate and event

A

Both are really similar in a way how they have a subscribed method list. When triggered they call a list of linked methods one by one.
**Differences: **
1. The main difference between an event and a delegate is that an event has an access level, which is typically set to protected or private, whereas a delegate does not. Events are not directly accessible to other classes, and other classes are not able to reassign it, or add or remove methods from its invocation list. Events can only be raised by the code in the same class, making it harder for other classes to accidentally modify the event’s invocation list.
2. Additionally, when you declare an event, the compiler automatically creates a private field which will store the delegate instance and provides add and remove methods which are used to handle += and -= operators respectively. These methods are thread-safe and make sure that multiple threads can’t modify the event’s invocation list simultaneously.
3. While both events and delegates use the += and -= operators for adding and removing subscribers, the way that the C# compiler handles these operators is different for events and delegates. When you use the += operator with a delegate, you are actually adding a new method to the delegate’s invocation list. On the other hand, when you use the += operator with an event, you are actually calling the add_PriceChanged method created by the compiler. This method is responsible for adding the new subscriber method to the event’s invocation list. This difference in how the += and -= operators are handled is important because events provide additional safeguards to ensure that the event’s invocation list is modified correctly, ensuring that multiple threads can’t modify the event’s invocation list simultaneously. In the case of a delegate, adding or removing methods from the invocation list is not thread-safe and might cause problems in multi-threaded environments.

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

What is a standart event pattern?

A

It is used to provide consistency across library and user code. The core is System.EventArgs predefined class with no members.
Pattern has three rules:
1. It must have void return type.
2. It must accept 2 arguments:
a) First of type object - indicates the event broadcaster
b) Second of subclass of EventArgs - contains the extra information to convey
3. Its name must end with EventHandler;
4. Requires that you write a protected virtual method that fires the event. It must be prefixed with ‘On’ and accept a single EventArgs argument:
~~~
protected virtual void OnPriceChanged(PriceChangedEventArgs e){
PriceChanged?.Invoke(this, e)
}
~~~

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

What are the event accesors? When is it useful to set custom accessors?

A

The accesors are the implementation of += and -= operators done by the compiler implicitly converting the event declaration.
It is converted to
1. private delegate field
2. public pair of event accessor functions that starts with add_eventName and remove_eventName

By setting explicit event accessors you can apply more complex strategies to the storage and access of underlying delegate.
Scenarios when this is useful:
a) When the event accessors are merely relays for another class that is broadcasting the event
b) When the class exposes many events for which most of the time very few subscribers exist, such as a Windows control. In such cases it is better to store the subscribers delegate instances in a dictionary because dictionary will contain less storage overhead than dozens of null delegate field references.
c) when explicitly implementing a interface that declares an event

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

What is a lambda expression?

A

(parameters) => expression-or-statement-block;
Lambda expression is an unnamed method written in place of a delegate instance. The compiler immediately converts it to either:
1. a delegate instance
2. An expression tree of type Expression<TDelegate> representing the code inside the lamda expression in traversable object model.
Lambda expressions are used most commonly with Func and Action delegates
~~~
Func<string, string, int> totalLength = (s1, s2) => s1.Length + s2.Length;
int total = totalLength (“Labas”, “vakaras”);
~~~

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

What is a captured variable?

A

Outer variables referenced by the lambda expresssions are called captured variables:
~~~
var factor = 2;
var multiplier = x => x * factor;
Console.Log(multiplier(3));
~~~
factor here is a captured variable.
Also, when a variable has been captured it’s lifetime is prolonged to be as of delegate which captured it

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

Why would we use static keyword on delegates?

A

This can be useful in micro-optimization scenarios to prevent unintentional memory allocation as it cannot reach local variables or it will throw compile error.
However if the labda doesnt capture variables the compiler will reuse a single cached instance across the life of application

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

Which is better to use (has more advantages in comparison): local method or lambda expression?

A

Local method.
Here’s why:
1. They can be recurssive (call themselves) without ugly hacks
2. They avoid the clutter of specifying a delegate
3. They incur slightly less overhead
Local methods are slightly more efficient because they avoid the indirection of a delegate.
They can also access local variables of containing method without some extra compiler work.

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

What is an anonymous method?

A

Anonymous method is like lambda expression but lacks:
1. Implicitly typed parameters
2. Expression syntax
3. The ability to compile to an expression tree by assigning to Expression<T>

As the name suggests, an anonymous method is a method without a name. Anonymous methods in C# can be defined using the delegate keyword and can be assigned to a variable of delegate type.
~~~
Print print = delegate(int val) {
Console.WriteLine(“Inside Anonymous method. Value: {0}”, val);
};

print(100); ~~~
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

What is a try statement?

A

A try statement specifies a code block subject to error-handling or cleanup code.
The try statement must be followed by one or more catch and/or a finally block (or both). The catch statement is executed when there’s an error in try block. Finally is executed after try and catch blocks to perform cleanup regardless if error was thrown or not.
Catch statement has access to an Exception object that contain information about the error

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

What are the benefits of catch clause?

A

Error handling: A catch clause allows you to handle errors that occur within the try block, so that your program can continue to run instead of crashing.

Improved debugging: By using a catch clause, you can add extra debugging information, such as logging the error message and stack trace, which can make it easier to understand what went wrong and how to fix it.

Code organization: Try-catch statements help you keep your code organized by separating the normal flow of control from the error handling code. This makes your code easier to read and understand.

Flexibility: A catch clause can catch multiple types of exceptions, which allows you to handle different types of errors in different ways if needed.

Defensive Programming: A catch block can also help in defensive programming to anticipate and manage exceptional conditions and avoid abrupt termination of program.

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

How can we add a special condition to catch clause?

A

By adding ‘when’ after the variable brackets like so:
~~~
catch (Webexception ex) when (ex.Status == Status.TimeOut)….
~~~

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

What is so specific about finally block?

A

It always gets called no matter what. The only exceptions are program crash or infinite loop somewhere else.
Most common practise is to use Dispose on an object within finally block

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

What is the connection between ‘using’ statement and try statement?

A

‘using’ statement implements IDisposable interface which when used sort of creates try-finally block. In this finally block a Dispose() method is implemented to clean up all unused resources left by previous object that needed this using statement.

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

Why should someone catch and exception and throw another type of exception in the same catch block?

A

Rethrowing a less-specific exception is something you might do when crossing a trust boundary so as not to leak technical information to potential hackers.

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

Lets say we cought an exceptio in catch block. How can we:
a) throw the original exception again?
b) throw new exception which is of the same type?

A

a) the original exception can be thrown by simply typing ‘throw’;
b) new exception of the same type will be thrown by typing “throw new SameException (“same old same”, ex);

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

What are the key properties of System.Exception?

A
  1. StackTrace: A string representing all the methods that are called from the origin of the exeption to the catch block;
  2. Message: A string with a description of the error;
  3. InnerException: The inner exception that caused the outer exception. This itself can have another InnerException
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

What most common exception types do you know?

A
  1. System.ArgumentException - generally indicates a bug.
  2. System.ArgumentNullException - unexpectedly the argument turned out to be null
  3. System.ArgumentOutOfRangeException - e.g. thrown when passing a negative number into a function that accepts only possitive values
  4. System.NotImplementedException - indicates that function has not yet been implemented
  5. System.NotSupportedException - particular functionality not supported e.g. adding a value to read only variable.
26
Q

What is the TryXXX method pattern?

A

We are talking about TryParse. In general this pattern offers its consumer both exception and return value in case of failure.
Use TryParse when you want to perform a conversion but want to check if the input string is a valid format before attempting the conversion. So that the program wont crash and we get a feedback + we dont need to use try-catch block for exception handling

27
Q

What is an enumerator?

A

An enumerator is a read-only, forward-only cursor over a sequence of values.
A type that follows any of these conditions:
1. has a public parameterless method named GetEnumerator that returns an enumerator
2. Implements System.Collections.Generic.IEnumeratable<T>
3. Implements System.Collections.IEnumerable
4. Can bind to an extension method named GetEnumerator that returns an enumerator
~~~
int[] numbers = {1, 2, 3};
IEnumerator enumerator = numbers.GetEnumerator();
while(enumerator.MoveNext())
{
int currentNumber = enumerator.Current;
Console.WriteLine(currentNumber);
}
~~~

28
Q

What happens under the hood when you instantiate and populate a collection?

A

using System.Collections.Generic
This:
List<int> list = new List<int> {1, 2, 3};
Gets translated into this:
~~~
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
~~~</int></int>

29
Q

What is the difference between return and yield return?

A

In a simple for loop ‘return’ would give us the entire list of values that was looped through while ‘yield return’ would give us the first value the loop encountered (e.g. 1), but the next time it is called it will return the next value after the one that was recently returned (e.g. 2)
Using yield return can simplify the implementation of the Iterator pattern and make it easier to generate sequences with a minimal memory overhead, which is useful in scenarios like dealing with large data sets.

30
Q

What is the purpose of nullable value types?

A

For reference types ‘null’ is a default value, therefore there will be no exception thrown, but value types like int and others does not allow to assett ‘null’ as their value, therefore we must denote the type with ‘?’ if we would like to make it nullable

31
Q

What happens when we try to compare nullable types like so:
~~~
int? x = 5;
int? y = 10;
var b = x < y;
~~~
How is it called?

A

Nullable types borrow underlying value types from their value, so the expression gets translated into this:
bool b = (x.HasValue && y.HasValue) ?
x.Value < y.Value : false;
In other words - if both x and y has values, it compares via INT’s less-than operator, otherwise returns false;
Its called operator lifting

32
Q

What happens when we try to add nullable types like so:
int? = 5;
int? = 10;
var b = x + y;

A

This will be translated as so:
var b = (x.HasValue && y.HasValue) ?
(int?) (x.Value + y.Value) : null;

33
Q

What will the result be?
1. null | null
2. null | false
3. null | true
4. null & null
5. null & false
6. null & true

A
  1. null
  2. null
  3. true (at least 1 should be true for expression to be true)
  4. null
  5. false (one false expression is enough to make all the result false)
  6. null
34
Q

When the nullable types are most useful? Give an example

A

Nullable types are particularly useful when representing unknown values, like for example if a class is mapped to nullable column values:
public decimal? AccountBalance;
this parameter would be mapped to null (when the table is newly created and there is no value yet. Without nullable types this would give us an error: AccountBalance = null;

35
Q

What is an ambient property?

A

A nullable type value property if null returns the value of its parent:
~~~
public Color Color{
get { return color ?? parent.Color;}
}
~~~

36
Q

Why is there a nullable reference type if the reference type default value is already ‘null’?

A

Nullable type for a reference types mean a bit different thing.
By making a reference type nullable we make it non-nullable. This helps to avoid NullReferenceException.
Plus we need to explicitly add a tag in our csproj file that we will be using non-nullable reference types
<Nullable>enable</Nullable>
After we add this element the reference types will not implicitly accept null as a value unless the ‘?’ is added after the type

37
Q

What is an extension method?

A

An extension method is a static method of a static class where the ‘this’ modifier is applied to the first parameter. The type of the first parameter is the type that is extended:
public static bool IsCapitalized(this string s){}
When compiled it is transformed into ordinary static method

38
Q

What is an anonymous type?

A

An anonymous type is a simple class created on the fly by the compiler to store a set of values. To create an anonymous type use the ‘new’ keyword followed by an object initializer, specifying the properties and values the type will contain:
var dude = new {Name = "Brad", Age=28};
After compilation this will be translated to a set of properties.
Important: The var keyword must be use.
If we need to set a return type for anonymous method we must use ‘object’ or ‘dynamic’ (The type of the dynamic variable is determined at runtime, rather than at compile-time.)

39
Q

What is the difference of a1.Equals(a2) versus a1 == a2?

A

Equals method is performing a structural equality comparison (comparison of the data). Whereas == performs referential comparison.

40
Q

What is a tuple?

A

Tuple provide a way to store a set of values. THe main purpose of tuples is to safely return multiple values without the need of using out parameters (something you cannot do with anonymous types):
var tuple = (name: "Bob", age:28);
Then: tuple.name // “Bob”
or name when specifying tuple types:
(string name, int age) tuple = ("Bob", 28);

41
Q

What is the difference between deconstructor and tuple syntax?

A

Deconstructor:
(string name, int age) = bob;
Tuple assignment:
(string name, int age) JOE = bob;

42
Q

What are records ?

A

A record is a special type of class designated to work well with immutable (read-only) data. Its most useful feature is nondestructive mutation; Also useful in creating types that just combine or hold data.
At compile time it is seemed as a simple class or struct.
Records implement structural equality meaning If the data is the same, then the objects are the same no matter the type.

43
Q

What is a nondestructive mutation?

A

Its when an immutable (read-only) entity is copied as a new one and the values are copied with some modification. Records do this in a more efficient way.

44
Q

What is happening to record during compilation?

A

A records is transformed into a class or struct and following is performed:
1. It writes a protected copy constructor (and a hidden Clone method) to facilitate nondestructive mutation;
2. It overrides/overloads the equality-related functions to implement structural equality;
3. It overrides the ToString() method (to expand the record’s public properties as with anonymous types)

45
Q

What happens to the records parameter list during compilation?

A

If a parameter list is specified the compiler performs the following extra steps:
1. It writes an init-only property per parameter
2. It writes a primary constructor to populate the properties
3. It writes a deconstructor

46
Q

What is a nondestructive mutation?

A

A non-destructive mutation in C# is a change to an object’s state that does not alter its behavior. In this example, the StringBuilder class allows us to modify the string value stored in sb without creating a new instance of the string. This is considered a non-destructive mutation because the original string value stored in sb is not destroyed or altered in any way, it is simply modified to create a new value.

// Create a string builder with the initial value of “Hello”
StringBuilder sb = new StringBuilder("Hello");

// Append “ World” to the string builder
sb.Append(" World");

// Get the final string from the string builder
string finalString = sb.ToString();

// Outputs: Hello World
Console.WriteLine(finalString);

47
Q

What are the nondestructive mutation’s phases?

A
  1. First, the copy constructor clones the record. By default it copies each of the records underlying fields, creating a faithful replica while bypassing (the overhead of) any logic in the init accessors. All fields are included (public and private as well as the hidden fields that back automatic properties)
  2. Then each property in the member initializer list is updated (this time using the init accessors)
48
Q

What is a primary constructor?

A

A primary constructor in C# is a constructor defined directly in a class declaration, rather than in the class body. It enables you to initialize a class instance directly with its constructor parameters, without having to write a separate constructor method.
~~~
public class Person
{
public string Name { get; set; }
public int Age { get; set; }

public Person(string name, int age)
{
    Name = name;
    Age = age;
} }

var person = new Person(“John Doe”, 30);
~~~

49
Q

Does records provide structural equality? What does it mean?

A

Yes they do. It means that if values of two structs are equal, the records are equal.
record1.Equals(record2) && record1 == records2; // true

50
Q

What is a ‘var pattern”?

A

The ‘var’ pattern is a variation of the ‘type’ pattern whereby you replace the type name with the ‘var’ keyword.
if we have this code:
~~~
bool IsJanetOrJohn (string name) {
string upper = name.ToUpper();
return upper == “JANET” || upper == “JOHN” }
```
We can translate to:

bool IsJanetOrJohn (string name) =>
name.ToUpper() is var upper && (upper == "JANET" || upper == "JOHN");

The ability to introduce and reuse an intermediate variable (upper in this case) in an expression-bodied method is convenient. Unfortunately it tends to be useful only when the method has a bool return type

51
Q

What is a ‘constant pattern’?
How it is different from ==?

A

The constant pattern lets you match directly to a constant and is useful when working with the object type:
void Foo (object obj){
` if (obj is 3) … } Equivalent to: obj is int && (int)obj == 3`

C# wont let you use == to compare object type directly to a constant because compiler needs to know the types in advance.
Alternative to this is : 3.Equals(obj);

52
Q

What is a relational pattern?

A

A relational pattern in C# is a pattern that allows you to match a value against a set of specified conditions, using the is keyword in combination with a relational operator (e.g. >, <, >=, <=, ==, !=). It is a feature introduced in C# 7.0, and can be used in the switch statement, the when clause of an if statement, and in other places.
~~~
int x = 150;

switch (x)
{
case int y when y < 100:
Console.WriteLine(“x is less than 100”);
break;
case int y when y >= 100 && y < 200:
Console.WriteLine(“x is between 100 and 200”);
break;
case int y when y >= 200:
Console.WriteLine(“x is greater than or equal to 200”);
break;
}
OR
int x = 5;
if (x is 5) {
Console.WriteLine(“x is equal to 5”);
} else {
Console.WriteLine(“x is not equal to 5”);
}
~~~

53
Q

What is the difference between && and “and” keyword?

A

The && operator and the and keyword in C# are both used for logical AND operations, but they have different purposes.

The && operator is used to perform a short-circuit evaluation of two boolean expressions. In other words, if the first expression is false, the second expression will not be evaluated, as the result of the operation is already known.
The and keyword, on the other hand, is used in pattern matching and is part of the relational pattern. It allows you to match a value against multiple conditions in a when clause. For example:
~~~
int x = 150;

switch (x)
{
case int y when y < 100:
Console.WriteLine(“x is less than 100”);
break;
case int y when y >= 100 and y < 200:
Console.WriteLine(“x is between 100 and 200”);
break;
case int y when y >= 200:
Console.WriteLine(“x is greater than or equal to 200”);
break;
}
~~~

54
Q

What are the pattern combinators?

A

From C#9 you can use ‘and’, ‘or’ and ‘not’ keywords to combine patterns:

bool IsJanetOrJohn (string name) => name.ToUpper() is "JANET" or "JOHN"
or
if (obj is not string) ...

55
Q

What is a property pattern?

A

A property pattern matches on one or more of an objects property values:
if (obj is string {Lenght:4}) ...

56
Q

What is a serialization?

A

The process of converting arbitrary objects to and from a particular format for storage or stransmission.

57
Q

Name few attributes and what they do

A

Obsolete attribute [Obsolete]:
If there is a reference to a class that is marked with ‘Obsolete’ attribute - a compiler will throw an warning
[Ignore] usually seen on test methods to go through them without running them.

58
Q

What is binding?

A

the process of resolving types, members, and operators, from compile time to runtime.

59
Q

Give an example of ‘dynamic’ type usage

A

Lets say we have this code
Duck d = ...
d.Quack(); // this works fine
Now if we wouls try to change the type of d to object, the line where method is called would cause a compile time error
object d =....
d.Quack(); // compile can’t know if this type has this method.
So here we can use ‘dynamic’ type, because it the actual type will be determined at run-time and after compilation we wont get any errors regarding this
dynamic d = ...
d.Quack(); // all good

60
Q

‘var’ vs ‘dynamic’

A
  • var : let the compiler figure out the type
  • dynamic: let the runtime figure out the type
61
Q

What are the uncallable functions?

A

Some functions cannot be called dynamically. You cannot call the following:
- Extension methods (via extension method syntax)
- Member of an interface, if you need to cast to that interface to do so
- Base members hidden by a subclass

62
Q

What are the native-sized integers?

A

The nint and nuint native-sized integer types are sized to match the adress space of the process at runtime. Native-sized integers can improve efficiency, overflow safety and convenience when performing pointer arithmetics
Usually when substracting two pointers the amount type is int64 (long), but if we cast pointers to the nint first the eresult of subtraction is also nint (which will be 32 bits