namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter09.Listing09_07
{
    using System;
    class Program
    {
        static void Main()
        {
            // ...

            Angle angle = new Angle(25, 58, 23);
            // Przykład 1. Prosta operacja opakowywania.
            object objectAngle = angle; // Opakowywanie.
            Console.Write(((Angle)objectAngle).Degrees);

            // Przykład 2. Wypakowywanie wartości, modyfikowanie wypakowanej wartości i usuwanie jej.
            ((Angle)objectAngle).MoveTo(26, 58, 23);
            Console.Write(", " + ((Angle)objectAngle).Degrees);

            // Przykład 3. Opakowywanie wartości, modyfikowanie opakowanej wartości i usuwanie referencji do niej.
            ((IAngle)angle).MoveTo(26, 58, 23);
            Console.Write(", " + ((Angle)angle).Degrees);

            // Przykład 4. Bezpośrednie modyfikowanie opakowanej wartości.
            ((IAngle)objectAngle).MoveTo(26, 58, 23);
            Console.WriteLine(", " + ((Angle)objectAngle).Degrees);

            // ...
        }
    }

    interface IAngle
    {
        void MoveTo(int hours, int minutes, int seconds);
    }

    struct Angle : IAngle
    {
        public Angle(int degrees, int minutes, int seconds)
        {
            _Degrees = degrees;
            _Minutes = minutes;
            _Seconds = seconds;
        }

        // UWAGA: ten kod sprawia, że typ Angle staje się zmienny.
        //        Jest to niezgodne ze wskazówkami.
        public void MoveTo(int degrees, int minutes, int seconds)
        {
            _Degrees = degrees;
            _Minutes = minutes;
            _Seconds = seconds;
        }

        public int Degrees
        {
            get { return _Degrees; }
        }
        private int _Degrees;

        public int Minutes
        {
            get { return _Minutes; }
        }
        private int _Minutes;

        public int Seconds
        {
            get { return _Seconds; }
        }
        private int _Seconds;
    }
}
