示例#1
0
        private static void CreateBookAndGetStatistics()
        {
            // The reference to this assembly allows me to use this class to introduce
            // speech into my program. It is loaded by the dynamic language runtime
            // when the class is requested
            //SpeechSynthesizer speech = new SpeechSynthesizer();
            //speech.Speak("Hello, welcome to this stupid gradebook program");

            GradeBook book = new GradeBook();

            try
            {
                Console.Write("Enter a name: ");
                // Ideally, you should not set the Name property until after you know you have
                // a valid value. You could do this by using a combination of a variable
                // and a loop which keeps prompting the user until they enter a valid value
                // and then, once they do, you are good to store the value of that variable
                // into the Name property
                book.Name = Console.ReadLine();
            }
            // Catch blocks can be chained and the first one to match will be the one that
            // executes and all the others will be skipped. Thus, include the most specific
            // exception blocks first.
            catch (ArgumentException ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            // The Exception type is the most general, from which most others inherit, so it
            // comes last. There are only a few which it cannot catch. These are the ones
            // that are guaranteed to crash your program. Catching one this general could
            // be dangerous since you don't know what kind of exception it is.
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            // Finally is good to add at the end to clean up any resources, regardless
            // of wheather or not there is an exception thrown.


            book.NameChanged = new NameChangedDelegate(OnNameChanged);
            //book.NameChanged = OnNameChanged; // sugar!

            // This is legal for delegates. But, if it were an event, you couldn't do this.
            // Usually, you should prefer events to provide encapsulation. Events bascially
            // translate into a private delegate behind the scenes which only publiclly expose
            // subscribe (+=) and unsubscripe (-=) methods.
            //book.NameChanged = OnNameChanged2; This will overwrite the delegate, effectively removing all subscribers.
            //book.NameChanged("Hehehehe", "I'm invoking the delegate directly from outside the class");

            book.NameChanged += OnNameChanged2;             // This creates a multicast delegate.

            book.NameChanged -= OnNameChanged2;             // Removes it from the multicast delegate


            // Events:
            book.NameChangedEvent += OnNameChanged;
            // You can only subscribe and unsubscribe from events. you cannot
            // invoke or assign to them directly but only from within the methods
            // of the class.
            //book.NameChangedEvent("This is no longer legal", "Compile Error!!!!");
            //book.NameChangedEvent = null; // Compile error!!

            // Events using convention with the title.
            book.TitleChanged += OnTitleChanged;
            book.Title         = "Title";

            // This will invoke the set method on the Name property, passing in
            // "Jeff's Grade Book" as the "value".
            book.Name = "Jeff's Grade Book";
            book.AddGrade(81);             // 81 is converted to a float
            book.AddGrade(75);
            book.AddGrade(91.5f);
            // book.AddGrade(53.4); // Compile error, cannot convert double to float.

            GradeStatistics stats = book.ComputeStatistics();

            WriteResult("Average", stats.AverageGrade);             // calls the one with a float result
            WriteResult("Highest", (int)stats.HighestGrade);        // calls the one with a int result (it truncates)
            WriteResult("Lowest", stats.LowestGrade);

            // You can't do this because you are in a static method. Non-static fields
            // and methods are implicitly passed 'this', which is a reference to the
            // object calling the method, which you don't have in a static method and
            // therefore cannot pass to the non-static method or field. In short, if you
            // are in a static method, you can only access other static methods/properties.
            //MyProperty = 3;
        }