Clase și obiecte

C# respectă paradigma programării orientate obiect. Programul reprezintă o colecție de obiecte ce interacționează între ele.

Obiectele au stări și comportamente. Clasele definesc structura obiectelor și a interacțiunii dintre ele.

În C# , pe lângă membri și metode , în clase putem defini și PROPRIETĂȚI. Acestea sunt metode implicite de set și get ce pot fi accesate ca niște membri.

    class Program
    {
        static void Main(string[] args)
        {
            Timp t = new Timp(1, 40, 0);
            t.Ore++;
            Console.WriteLine(t.Ore.ToString());
            Console.ReadKey();
        }
    }

    class Timp
    {
        //membri
        int ore, minute, secunde;
        //constructor
        public Timp(int i_ore, int i_minute, int i_secunde)
        {
            ore = i_ore;
            minute = i_minute;
            secunde = i_secunde;
        }

        //proprietate
        public int Ore
        {
            //getter
            get { return ore; }
            //setter, observati cuvantul cheie value
            set { ore = value; }
        }
    }
        

Interfețe și moștenire

În C# avem 4 tipuri de modificatori de access ai componentelor claselor:

  • public:membrul nu este restricționat.
  • internal:accesul este limtat la dll-ul curent.
  • protected:accesul este limitat la clasa curentă și clasele care o moștenesc.
  • privat:membrul este accesibil doar din clasa curentă.

Interfețele reprezintă contracte pe care clasele se obligă să le implementeze. Ele sunt definite prin cuvântul cheie interface și pot contine proprietăți metode și eventuri.Ele sunt definite fără modificatori de access.

    //puteti sa va imaginati un stecher de aparat electrocasnic. 
    interface IConsumator
    {
        void ConsumCurent(int consum);
    }
    interface IPriza
    {
        //Priza este o interfata pe care instalatia electrica o implementeaza.
        //Astfel consumatorii pot fi connectati la sursa de electricitate prin intermediul acestei interfete.
        void ConnectareConsumator(IConsumator consumator);
    }
        

În C# o clasă poate moștenii dintr-o singură clasă, însă poate implementa mai multe interfețe.

    public class Drujba
    {
        protected int putere;

        public Drujba(int i_putere)
        {
            putere = i_putere;
        }

        public void Taie() {}
    }

    public class DrujbaElectrica : Drujba, IConsumator
    {
        public DrujbaElectrica(int I_consum):
            base(I_consum)
        {        
        }

        public void ConsumCurent(int consum)
        {
        }
    }
        

Polimorfism

C# suportă atât polimorfismul de compilare ( overloading-ul ) cât și cel de execuție ( overriding ).

    class Program
    {
        static void Main(string[] args)
        {
            ExecutieProgram(new TelefonMobil(1245), new Telefon4G(3212));
            Console.ReadKey();
        }

        static void ExecutieProgram(TelefonMobil t1, TelefonMobil t2)
        {
            //polimorfism de compilare. Stim ce metoda se va apela dupa signatura ei.
            t1.SunaNumar(123);
            t1.SunaNumar("321");
            //poliorfism de executie
            t1.ConnectareRetea();
            t2.ConnectareRetea();
        }
    }

    public class TelefonMobil
    {
        protected int m_numar;

        public TelefonMobil(int numar)
        {
            m_numar = numar;
        }

        // va apela ultimul numar format
        public void SunaNumar()
        { 
        }
        //va apela numarul trimis ca parametru
        public void SunaNumar(int numar)
        {
            Console.WriteLine(numar.ToString());
        }
        public void SunaNumar(string numar)
        {
            Console.WriteLine(numar);
        }
        
        public virtual void ConnectareRetea()
        {
            Console.WriteLine("Connectare retea");
        }
    }

    public class Telefon4G : TelefonMobil
    {
        public Telefon4G(int numar) : base(numar) { }

        public override void ConnectareRetea()
        {
            Console.WriteLine("Connectare retea LTE!");
        }
    }

        

Supraîncărcarea operatorilor este de asemenea posibilă. Tutorial MicroSoft

C# suporta clase template. System.Collection are implementate mai multe astfel de clase : List<> , Dictionary<,> , etc.

            List iList = new List();
            iList.Add(3);
            Dictionary capitale = new Dictionary();
            capitale.Add("Romania", "Bucuresti");
        

LINQ

O funcționalitate importantă adaugată în .NET 3.5 a fost suportul pentru Extension Methods si Programarea Functională care au permis realizarea framework-ului LINQ.

Operatorul => a fost adăgat și se citește Goes to . El se mai numește și operatorul lambda și este folosit în expresii lambda. Are rolul de a separa în partea stangă variabila de către corpul expresiei. Expressile lamda sunt funcții inline anonime.

Extension Methods este un mecanism prin care putem adauga functionalitati noi frameworkului existent.

    namespace ExtensionMethods
    {
          public static class MyExtensions
          {
              public static int WordCount(this String str)
              {
                   return str.Split(new char[] { ' ', '.', '?' }, 
                             StringSplitOptions.RemoveEmptyEntries).Length;
              }
           }   
    }

    using ExtensionMethods;

    string s = "Hello Extension Methods";
    int i = s.WordCount();

         

LINQ (Language Integrated Query) este o componentă a .NET ce adaugă capabilități de interograre a collecțiilor.

         Dictionary telefoane = new Dictionary();
         telefoane.Add("Lumia", new Telefon4G(1));
         telefoane.Add("iPhone", new Telefon4G(2));
         telefoane.Add("huawei", new TelefonMobil(3));
         //selectati toate numele telefoanelor 4g si inseratile intr-o lista.
         //.. 
         var telefoane4g = telefoane.Where(item => item.Value is Telefon4G)
                                    .Select(item => item.Key)
                                    .ToList();
         

Exerciții

1) Complex Numbers 


A complex number has two parts: the real part and the imaginary part. In a number such as a+bi (2-3i, for example) the real part would be "a" (2) and the imaginary part would be "b" (-3). 
Create a class ComplexNumber with: 
A constructor to set the values for the real part and the imaginary part. 
Setters and getters for both. 
A method "ToString", which would return "(2,-3)" 
A method "GetMagnitude" to return the magnitude of the complex number (square root of a2+b2) 
A method "Add", to sum two complex numbers (the real part will be the sum of both real parts, and the imaginary part will be the sum of both imaginary parts) 
Create a test program, to try these capabilities. 

2) Realizați o clasă numită Ceas. Această clasă trebuie să publice o proprietate numită ora curentă care să poată să fie setată. Clasa trebuie sa suprascrie metoda ToString().
Ceasul trebuie impleteze și o metoda numită Tick(), care să incremente timpul cu o secundă. Se va folosi Thread.Sleep(999) pentru implementarea ei.

3) Folosind clasa de la exercițiul 2), implementați o noua clasa care o extinde pe prima si implementează interfața 

    public delegate void AlarmEvent(string name);

    interface IAlarma
    {
        void SetAlarma(string name, DateTime date);
        event AlarmEvent Alarm;
    }
    Cea de-a doua clasă se va numi CeasDesteptator. Metoda Tick() va trebui făută virtuala in clasa de bază și suprascrisă în clasa derivată.

4) Utilizând LINQ creați o metodă în clasa CeasDesteptator numită 
    string UrmatoareaAlarma(string nume)
    care va returna următoarea dată când va fi pornită alarma pentru un eveniment având numele primit ca parametru.
   
         

Update 30 octombrie !

Rezolvari

         
    class Ceas
    {
        //membri
        int ore, minute, secunde;
        protected DateTime m_time;
        //constructor
        public Ceas(int i_ore, int i_minute, int i_secunde)
        {
            ore = i_ore;
            minute = i_minute;
            secunde = i_secunde;
            m_time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, i_ore, i_minute, i_secunde);
        }
        //proprietate
        public int Ore
        {
            //getter
            get { return m_time.Hour; }
            //setter, observati cuvantul cheie value
            set
            {
                m_time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
                    value, m_time.Minute, m_time.Second);
            }
        }
        public virtual void Tick()
        {
            this.m_time = this.m_time.AddSeconds(1);
            Thread.Sleep(999);
        }
        public override string ToString()
        {
            return m_time.ToLongTimeString();
        }
    }

    class CeasDesteptator : Ceas, IAlarma
    {
        Dictionary<string, DateTime> m_alarme;
        public CeasDesteptator(int i_hour, int i_minutes, int i_seconds)
            : base(i_hour, i_minutes, i_seconds)
        {
            m_alarme = new Dictionary<string, DateTime>();
        }
        public void SetAlarma(string name, DateTime date)
        {
            if (!m_alarme.ContainsKey(name))
            {
                m_alarme.Add(name, date);
            }
        }
        public event AlarmEvent Alarm;
        public override void Tick()
        {
            base.Tick();
            foreach (string alarma in m_alarme.Keys)
            {
                if (m_alarme[alarma] == m_time && Alarm != null)
                {
                    Alarm(alarma);
                }
            }
        }
        public string UrmatoareaAlarma(string nume)
        {
            return m_alarme.Where(item => item.Key == nume)
                           .Select(item => item.Value)
                           .First()
                           .ToString();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            CeasDesteptator t = new CeasDesteptator(16, 48, 51);
            Console.WriteLine(t.ToString());
            t.SetAlarma("goToSchool", new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
                16, 48, 57));
            t.Alarm += new AlarmEvent(ShowAlarm);
            Console.WriteLine(string.Format("Urmatoarea alarma:{0}", t.UrmatoareaAlarma("goToSchool")));
            for (int i = 0; i < 7; i++)
            {
                t.Tick();
            }
            Console.ReadKey();
        }
        public static void ShowAlarm(string nume)
        {
            Console.WriteLine(nume);
        }
    }