Porównanie przeciążeń metody "list.Sort()"

0

Szanowni Państwo,

Mam tutaj dość prosty, acz przydługawy, program sortujący listę.

  1. Metoda "sort()" ma dwa przeciążenia. Jedno z obiektem klasy która dziedziczy "IComparable<>" a drugie klasy "Comparison<>". Co nam to w sumie zmienia czy użyjemy jednego sposobu czy drugiego? czyt. która metoda jest lepsza? Oba te sposoby opierają się stworzeniu obiektu będącego delegatem?

  2. Za pomocą
    listPersonel.Sort(delegate (Personel c1, Personel c2) { return c1.Name.CompareTo(c2.Name); });
    tworzymy obiekt (delegat) anonimowy który przekazujemy funkcji sortującej. Jakie są zalety korzystania z obiektów anonimowych?

  3. Jeśli użyjemy "Peek definition" na klasie "Comparision" to będziemy mieli:
    public delegate int Comparison<in T>(T x, T y);
    Co oznacza fragment <in T> ?

Tutaj kod programu:

using System;
using System.Collections.Generic;

namespace IntroductionIntoCsharp22
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Hello World!");

            //Utworzenie listy instancji klasy Personel
            List<Personel> listPersonel = new List<Personel>();
            listPersonel.Add(new Personel("John", 4500));
            listPersonel.Add(new Personel("Hawking", 3500));
            listPersonel.Add(new Personel("Olek", 2500));

            //Wyświetlenie listy personelu
            foreach (Personel person in listPersonel)
            {
                Console.WriteLine(person.ID + " " + person.Name + " " + person.Salary);
            }

            //Posortowanie listy po zarobkach według wewnętrznej metody
            listPersonel.Sort();

            Console.WriteLine("\nPosortowane po zarobkach");
            //Wyświetlenie listy personelu
            foreach (Personel person in listPersonel)
            {
                Console.WriteLine(person.Name + " " + person.Salary);
            }

            //Utworzenie obiektu klasy "SortByName" i przekazanie go, jako argument, funkcji sortującej.
            SortByName objekt = new SortByName();
            listPersonel.Sort(objekt);

            Console.WriteLine("\nPosortowane po imionach");
            //Wyświetlenie listy personelu
            foreach (Personel person in listPersonel)
            {
                Console.WriteLine(person.Name + " " + person.Salary);
            }

            //Utworzenie instancji obiektu będącego delegatem "Comparision" do porównania po zarobkach
            Comparison<Personel> personelComparer = new Comparison<Personel>(ComparePersonel);
            //Wywołanie funkcji sortującej listę po zarobkach
            listPersonel.Sort(personelComparer);                       
           
            Console.WriteLine("\nPosortowane po zarobkach");
            //Wyświetlenie listy personelu
            foreach (Personel person in listPersonel)
            {
                Console.WriteLine(person.ID + " " + person.Name + " " + person.Salary);
            }

            //Utworzenie anonimowego obiektu będącego delegatem porównującym dwa obiekty po imieniu
            listPersonel.Sort(delegate (Personel c1, Personel c2) { return c1.Name.CompareTo(c2.Name); });

            Console.WriteLine("\nPosortowane po imionach");
            //Wyświetlenie listy personelu
            foreach (Personel person in listPersonel)
            {
                Console.WriteLine(person.ID + " " + person.Name + " " + person.Salary);
            }

            //Utworzenie, za pomocą wyrażenia lambda, anonimowego obiektu będącego delegatem porównującym po dwa obiekty po imieniu
            listPersonel.Sort((x, y) => x.ID.CompareTo(y.ID));

            Console.WriteLine("\nPosortowane po ID");
            //Wyświetlenie listy personelu
            foreach (Personel person in listPersonel)
            {
                Console.WriteLine(person.ID + " " + person.Name + " " + person.Salary);
            }

            Console.ReadKey();
        }

        //Definicja, za pomocą wyrażenia lambda, klasy porównującej dwa obiekty tego samego typu po zarobkach
        private static int ComparePersonel(Personel x, Personel y) => x.Salary.CompareTo(y.Salary);
    }

    //definicja klasy Personel
    class Personel : IComparable<Personel>
    {
        static int Pop = 0;
        public int ID { get; }
        public string Name { get; }
        public int Salary { get; }

        public Personel(string name, int salary)
        {
            Pop++;
            this.ID = Pop;
            this.Name = name;
            this.Salary = salary;
        }
        //Funkcja interfejsu "IComparable<>" porówująca dwa obiekty po zarobkach
        public int CompareTo(Personel obj)
        {
            return this.Salary.CompareTo(obj.Salary);
        }
    }
    //Definicja klasy porównująca obiekty po imieniu
    class SortByName : IComparer<Personel>
    {
        public int Compare(Personel obj1, Personel obj2)
        {
            return obj1.Name.CompareTo(obj2.Name);
        }
    }
}
2

To jest kontrawariantny parametr typu , jeszcze są kowariantne parametry typu ze słowem kluczowym out.
To nie jest żadna nowość . Takie parametry zostały wprowadzone w C# 4. W książkach mało albo nic nie ma na ich temat.
Takie parametry można stosować w interfejsach i delegatach.

taki krótki przykład o co w tym wszystkim biega ;)

using System;
namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            Generyczna<Bazowa> ob1 = new Generyczna<Bazowa>();
            Generyczna<Pochodna> ob2 = new Generyczna<Pochodna>();

            IjakisInterfejs1<Bazowa> in1 = ob2;

            IjakisInterfejs2<Pochodna> in2 = ob1;


        }
    }

    public interface IjakisInterfejs1<out T> { T Metoda1(); }
    public interface IjakisInterfejs2<in T> { void Metoda2(T par); }
    class Bazowa
    {
    }

    class Pochodna : Bazowa
    {
    }

    class Generyczna<T> : IjakisInterfejs1<T>, IjakisInterfejs2<T>
    {
        T x;

        public T Metoda1()
        {
            return x;
        }

        public void Metoda2(T par)
        {
            x = par;
        }
    }
}
0
lion137 napisał(a):

Do poczytania:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-generic-modifier
https://stackoverflow.com/questions/3498891/system-comparisont-understanding#3498918
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)

EDYCJA: Znów mi widzę linka z Wiki niepoprawnie wkleja, @cerrato, @somekind , trzeba tu jakiegos buga zgłosić, czy coś? W każdym razie zobacz tu:
https://duckduckgo.com/?t=canonical&q=covariance+and+contravariance+computer+science&atb=v219-1&ia=web
Pierwszy wynik.

  1. Czyli "Comparison<>" jest delegatem, czyli po prostu obiektem który wskazuje na funkcję i może być traktowany jak funkcja? W przypadku "IComparer<>" musimy napisać nową klasę która dziedziczy po interface "IComparer<>" i dopiero obiekt tej nowej klasy przekazać jako argument?
  2. Czy wyrażenie lambda też jest takim obiektem anonimowym?
  3. Chyba nie rozumiem. Czyli <in T> po prostu pozawala nam wywoływać metodą na obiektach klasy "T" i wszystkich pochodnych?

1 użytkowników online, w tym zalogowanych: 0, gości: 1