using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Varianz
{
   class Base           {};
   class Derived : Base {};


   interface IKovarianz<out T>
   {
      T doSomething();
   };

   interface IKontravarianz<in T>
   {
      void doSomething(T obj);
   };

   class ObjectGeneratorA<T> : IKovarianz<T> where T : new()
   {
      public T doSomething() { return new T(); }
   };

   class ObjectGeneratorB<T> : IKontravarianz<T> 
   {
      public void doSomething(T obj) { Console.WriteLine(obj.GetType().Name); }
   };



   class Program
   {
      static void Main(string[] args)
      {
         {
            Derived d = new Derived();
            Base b = d;

            Console.WriteLine(b.GetType().Name);
         }

         {
            IKovarianz<Derived> d = new ObjectGeneratorA<Derived>();
            IKovarianz<Base> b = d;

            Console.WriteLine(b.GetType().Name);
            Console.WriteLine(b.doSomething().GetType().Name);
         }

         {
            Base b = new Derived();
            Derived d = (Derived) b;

            Console.WriteLine(d.GetType().Name);
         }

         {
            IKontravarianz<Base> b = new ObjectGeneratorB<Base>();
            IKontravarianz<Derived> d = b;

            d.doSomething(new Derived());
         }


         IEnumerable<string> lines = new List<string>();
         IEnumerable<object> objects = lines;

      }
   }
}
