1.3. fejezet, Generikusok és Lambda

Az alábbi statikus tagok kivételével a generikus osztályok kezelése hasonló a Java-hoz.

    class Test<T>
    {
        static public int Value;
    }
 
    class GenericsTest
    {
        static public void GenericList()
        {
            Console.WriteLine("=================== GenericsTest =================");
            SortedList<string, int> list = new SortedList<string, int>();
            list.Add("egy", 1);
            list.Add("kettõ", 2);
            list.Add("három", 3);
 
            foreach (KeyValuePair<string, int> item in list)
            {
                Console.WriteLine("Kulcs == {0}, Érték == {1}",
                item.Key, item.Value);
            }
        }
 
        static public void GenericStatic()
        {
            Test<int>.Value = 10;
            Test<string>.Value = 20;
            Console.WriteLine(Test<int>.Value);
            Console.WriteLine(Test<string>.Value);
        }
    }

További megszorításokat tehetünk a where kulcsszóval:

    class Test<T>
    {
        static public int Value;
    }
 
    class Test<T>
        where T : class
    {
    }
 
    class Test<T>
        where T : struct
    {
    }
 
    class Test<T>
        where T : IEnumerable
    {
    }
 
    class Test<T>
        where T : new() //csak olyan osztály lehet, aminek van alapértelmezett konstruktora
    {
    }
 
    class Test<T, U>
        where T : U //T csak U vagy annak leszármazottja lehet
    {
    }
 
    //Pl.:
    class Base { }
 
    class Derived : Base { }
 
    class Test<T>
        where T : Base
    {
    }
 
 
    class MyClass<T> : IEnumerable<T>, IEnumerator<T>
    {
    }

Koveriencia (covariance) és kontravarencia (contravariance)

Mivel a .NET-ben nem kompatibilis két generikus változó, még akkor sem, ha polimorfizmus elve szerint az lenne, az alábbi kód érvénytelen:

  List<Student> studentList = new List<Student>();
  List<Person> personList = studentList;

Ezért kitalálták a következőt:

        static public void GenericCovariance()
        {
            Method<Person> m1 = (person) => Console.WriteLine(person.Age);
            Method<Student> m2 = m1;
            Student s = new Student() { Age = 24, Name = "Éva" };
            m1(s); // 24
            m2(s); // 24
        }

A generikus List és hasonló osztályok fel vannak készítve a covariance-re:

    class Person
    {
        public int Age;
    }
 
    class Student : Person
    {
        public string Name { get; set; }
    }
 
    static public void GenericClassNInterfaces()
    {
        IEnumerable<Student> sie = new List<Student>()
        {
            new Student() { Name = "Géza", Age = 22 },
            new Student() { Name = "Éva", Age = 26 },
        };
        IEnumerable<Person> pie = sie;
        foreach (Person person in pie)
        {
           Console.WriteLine("Életkor: {0} ", person.Age);
        }
 
    }

Egy lambda kifejezés megfelel egy névtelen metódus definíciónak:

        public delegate int IntFunc(int x);
 
        static public void LambdaTest()
        {
            IntFunc func = (x) => (x * x);
            Console.WriteLine(func(10)); // 100
 
            Func<int, int, bool> func2 = (x, y) => (x > y);
            Console.WriteLine(func2(10, 5)); // true
 
            Func<bool> func3 = () => true;
            Console.WriteLine(func3()); //true
 
            //Void lambda
            Action<int> act = (x) => Console.WriteLine(x);
            act(10);
        }

Kifejezés fa

using System.Linq.Expressions;
...
 
  Expression<Func<int, int, bool>> expression = (x, y) => (x > y);
  Console.WriteLine(expression.Compile().Invoke(10, 2)); // True
 
...