// CompCS
using System;
namespace CompCS {
 public class Top {}
 public class Middle: Top {}
 public class Bottom: Middle{}

 public class Up {
  public void cv(Top t){
   Console.WriteLine("cv(T) in Up using C#!");
  }

  public void ctv(Bottom b){
   Console.WriteLine("ctv(B) in Up using C#!");
  }
 }
}

//ClientCSCS
using System;
using CompCS;

public class Down: Up {

 // covariant redefinition
 public void cv(Middle m){
  Console.WriteLine("cv(M) in Down using C#!");
 }

 // contravariant redefinition
 public void ctv(Middle m){
  Console.WriteLine("ctv(M) in Down using C#!");
 }

    // Static method called "Main" is application's entry point function
    public static void Main() {

  Down d = new Down(); // always the same

  Console.WriteLine("-- Calls C# from C# --");
  Up u = new Up();
  Up ud = new Down();

  Console.WriteLine(" Up u");
  u.cv(new Top());
  u.cv(new Middle());
  u.cv(new Bottom());
  //u.ctv(new Top());
  Console.WriteLine("Compilation error");
  //u.ctv(new Middle());
  Console.WriteLine("Compilation error");
  u.ctv(new Bottom());
  Console.WriteLine(" Down d");
  d.cv(new Top());
  d.cv(new Middle());
  d.cv(new Bottom());
  //d.ctv(new Top());
  Console.WriteLine("Compilation error");
  d.ctv(new Middle());
  d.ctv(new Bottom());
  Console.WriteLine(" Up ud");
  ud.cv(new Top());
  ud.cv(new Middle());
  ud.cv(new Bottom());
  //ud.ctv(new Top());
  Console.WriteLine("Compilation error");
  //ud.ctv(new Middle());
  Console.WriteLine("Compilation error");
  ud.ctv(new Bottom());
    }
}

-- Calls C# from C# --
 Up u
cv(T) in Up using C#!
cv(T) in Up using C#!
cv(T) in Up using C#!
Compilation error
Compilation error
ctv(B) in Up using C#!
 Down d
cv(T) in Up using C#!
cv(M) in Down using C#!
cv(M) in Down using C#!
Compilation error
ctv(M) in Down using C#!
ctv(M) in Down using C#!
 Up ud
cv(T) in Up using C#!
cv(T) in Up using C#!
cv(T) in Up using C#!
Compilation error
Compilation error
ctv(B) in Up using C#!