This is the third part of the Higher Kinded Types in C# series. For your convenience you can find other parts in the table of contents in Part 1 — Introduction

This time we start with this invoice:

Obviously, this breaks things now. We need to add these two things to Brand:

Since we cannot use covariance and contravariance easily, we need to do upcasting and downcasting in generics “the hard way”.

We create invoice this way:

Okay, now how to process it? We’d like to have one function translating Started< T> into Finished< T> and we already have it, it’s called Finish. How to reuse it?

We cannot use it directly as it works on Started< T> type. But we cannot use FinishBrand method either because then compiler will go crazy as it cannot handle one lambda for Started< string> and Started< int>. What can we do? Upcasting and downcasting:

So we accept lambda working on the base type object. The trick is, we can transform original lambda in this way:

So we just magically transform lambdas using upcasting and downcasting.

Let’s see this in action: