Skip to content

Commit

Permalink
Adding notes on generic types.
Browse files Browse the repository at this point in the history
  • Loading branch information
Clément committed Sep 18, 2024
1 parent 76a6a52 commit 64a7734
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 1 deletion.
2 changes: 1 addition & 1 deletion source/lectures/arrays/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ tags:
- datatypes/collections
---

# Arrays
# Introduction

Arrays are structures that allow you to store multiple values in memory using a single name and indexes.
Internally, an array contains a fixed number of variables (called *elements*) of a particular type^[Usually, all the elements of an array have the same type, but an array can store elements of different types if `object` is its type, since any element is actually of type `object`.].
Expand Down
128 changes: 128 additions & 0 deletions source/lectures/oop/generic_types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
tags:
- oop
- datatypes/collections
---

# Generic Type Parameter

## Introduction

Imagine that you want to write a method that takes as an argument an array and returns an array of the same type, but with the values reversed.
You may write the following code:

```
public class Helper{
public static int[] Reverse(int[]] arrayP)
{
int[] result = new int[arrayP.Length];
int j = 0;
for (int i = arrayP.Length - 1; i >= 0; i--)
{
result[j] = arrayP[i];
j++;
}
return result;
}
}
```

Then, this method could be used as follows:

```
int[] array1 = {0, 2, 3, 6};
int[] array1reversed = Helper.Reverse(array1);
```

And then `array1reversed` would contain 6, 3, 2, 0.

This method works as intended, but you can use it only with arrays of *integers*.
If you want to use a similar method with arrays of, say, `char`, then you need to copy-and-paste the code above and to replace every occurrence of `int` by `char`.
This is not very efficient, and it is error-prone.

## Generic Types

There is a tool in C# to avoid having to be *too* specific, and to be able to tell the compiler that the method will work "with some type", called [generic type parameter](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/generic-type-parameters), using the keyword `T`.
In essence, `<T>` is affixed after the name of the method to signal that the method will additionally require to instantiate `T` with a particular type.

The previous method would become:

```
public class Helper{
public static T[] Reverse<T>(T[] arrayP)
{
T[] result = new T[arrayP.Length];
int j = 0;
for (int i = arrayP.Length - 1; i >= 0; i--)
{
result[j] = arrayP[i];
j++;
}
return result;
}
}
```

where three occurrences of `int[]` were replaced by `T[]`, and `<T>` was additionally added between the name of the method and its parameters. This method is used as follows:

```
int[] array1 = {0, 2, 3, 6};
int[] array1reversed = Helper.Reverse<int>(array1);
char[] array2 = {'a', 'b', 'c'};
char[] array2reversed = Helper.Reverse<char>(array2);
```

In essence, `Reverse<int>` tells C# that `Reverse` will be used with `T` being `int` (not `int[]`, as the method uses `T[]` for its argument and return type).
Note that to use *the same method* with `char`, we simply use `Reverse<char>`, and then we provide an array of `char` as parameters, and obtain an array of `char` in return.

## Implicitly Typed Local Variables

Sometimes, the body of the method needs to declare variable with the same type as `T`.
Indeed, imagine, for example, that we want to add to our `Helper` class a method that returns a `string` description of an array.
We can write the following:

```
public static string Description(int[] arrayP)
{
string returned = "";
foreach (int element in arrayP)
{
returned += element + " ";
}
return returned;
}
```

but this method is specific to arrays of `int`, and we would have to write another one for `char`, for example.
Making the header generic is "easy", as we can use, as before:

```
public static string Description<T>(T[] arrayP)
```

but the body is problematic: what should be the type of the `element` variable in the header of the `foreach`? We cannot simply use `T`, but we can use *implicitly typed variable*.
This technique, that uses the keyword `var` essentially tells C# to … figure out the type of the variable.
In that case, since C# knows the type of the array you are passing, it can easily infer the type of its elements.

We can then rewrite the previous method as follows:

```
public static string Description<T>(T[] arrayP)
{
string returned = "";
foreach (var element in arrayP)
{
returned += element + " ";
}
return returned;
}
```

and use it with

```
Console.WriteLine(Helper.Display<char>(array2);
```

for example.
1 change: 1 addition & 0 deletions source/order
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
./lectures/oop/more_advanced_object_concepts.md
./lectures/oop/properties.md
./lectures/oop/static.md
./lectures/oop/generic_types.md
./lectures/flow/
./lectures/flow/flow_intro.md
./lectures/flow/booleans.md
Expand Down

0 comments on commit 64a7734

Please sign in to comment.