ClassesYou saw a class structure in the "Hello, C# World!" sample. In the C#, you define a class by using the class keyword, just as you do in C++. Following the class keyword the class name and curly brackets ({. . .}), as shown here:class Hello{ static void Main() { Console.WriteLine("Hello, C# World!"); }}Note: C# classes don't end semicolon (;) as C++.Once a class is defined, you can add class members to it. Class members can include constants, fields, methods, properties, indexers, events, operators, instance constructors, static constructors, destructors, and nested type declarations. Each class member has an associated accessibility, which controls the scope of the member and defines whether these members are accessible outside the class.Class MembersTable 1-9 describes allowable class member elements.Table 1-9 allowable class member elements
Before examining these members in detail, you'll look at the accessibility of these members. Table 1-10 describes class member accessibility type and their scopes.
Now you'll look at class members in more detail.FieldsA field member Represent a variable of a class. In this example, strClassName is a string type public variable that can be accessed by the class instance:class myClass { public static string strClassName; public void SetClassName(string strName) { strClassName = strName; } }As noted earlier; you can define field members as read-only. This means the field can only be assigned in the declaration or in the constructor of the class. See the following code:class myClass{ public static readonly string strClassName = "myClass"; public void SetClassName(string strName) { strClassName = strName; // illegal assignment }}Note that the complier will throw an error because of an illegal assignment.If the field is not static, you have to access fields from the class instance. It's the same idea as accessing a public variable in the C++ or structure in C. for example:myClass cls = new MyClass();
string clsName = cls.strClassName;ConstantsA constant Member represents a constant value throughout the program. For example the clsNodes is constant that has integer value 12. See the following code:class myClass { public const int clsNodes = 12;}The value of clsNodes will be 12 throughout the program and can't be reassigned.Instance and Static ConstructorsConstructors in C# are defined in the same way as in C++. C# supports two types of constructors: instance constructors and static constructors. Instance constructors are called every time a class is initialized. Static constructors are executed only once. Static constructors are for initialing the values of static variable. Listing 1-25 is an example of a class with a static constructor.Listing 1-25 Calling Static Constructorsusing System;class myClass{ static myClass() { Console.WriteLine("Initialieze clas "); } public static void foo() { Console.WriteLine(" foo"); }}class Test{ static void Main() { myClass.foo();//class myClass static constucter and then foo }}Constructors can be overloaded, as shown in listing 1-26.Listing 1-26. Over loaded Constructors exampleclass myClass{ public int iCounter, iTotal; public myClass() { iCounter = 0; iTotal = 0; } public myClass(int iCount, int iTot) { iCounter = iCount; iTotal = iTot; }}Listing 1-27. Calling class constructorsusing System;class myClass{ public int iCounter, iTotal; public myClass() { iCounter = 0; iTotal = 0; } public myClass(int iCount, int iTot ) { iCounter = iCount; iTotal = iTot; }}
class TestmyClass { static void Main() { myClass cls = new myClass(); myClass cls1 = new myClass(3, 4); Console.WriteLine(cls1.iCounter.ToString()); Console.WriteLine(cls1.iTotal.ToString()); }}DestructorsA destructor is called when it's time to destroy the object. Destructors can't take parameters. See following code:class myClass{ ˜ myClass() { // free resources }}TIP: It's not compulsory_ in fact it's unadvisable_ to call destructors. They're called automatically by the CLR when it destroys the object during garbage collection.MethodsA method is a member that implements some functionality. It's similar in appearance to the methods found in C++ and java. A method can return a value have, a list of parameters, and can be accessed through the class, whereas non - static. Static methods are accessed through the class, whereas non-static methods are accessed through the instance of the class. For example, listing 1-28 adds a method sum to the class myClass and called this method from the Main method.Listing 1-28 Class method exampleusing System;class myClass{ public int Sum(int a, int b) { int res = a + b; return res; }}class TestmyClass{ static void Main() { myClass cls = new myClass(); int total = cls.Sum(5, 8); Console.WriteLine(total.ToString()); }}Methods in C# support function overloading in a similar way as C++. If you have programmed in C++, you'll notice that C# methods are similar to C++ functions (and almost mirror those methods found in java). So it's not a bad idea to call function overloading in C# method overloading. In listing 1-29, I over- overload the Sum method by passing in different types of values and call each of the overloaded Sum methods from the Main method.Listing 1-29 Method overloading exampleusing System;class myClass { public int Sum(int a, int b) { int res = a + b; return res; } public float Sum(float a, float b) { float res = a + b; return res; } public long Sum(long a, long b) { long res = a + b; return res; } public long sum(long a, long b, long c) { long res = a + b + c; return res; } public long Sum(int[] a) { int res = 0; for (int i=0; i < a.Length; i++) { res += a[i]; } return res; } public void Sum() { //return nothing }}class TestmyClass{ static void Main() { myClass cls = new myClass(); int intTot = cls.Sum(5,8); Console.WriteLine("Return integer sum:"+ intTot.ToString()); cls.Sum(); long longTot = cls.Sum(Int64.MaxValue - 30, 8); Console.WriteLine("Return long sum:" + longTot.ToString()); float floatTot = cls.Sum(Single.MaxValue-50, 8); Console.WriteLine("Return float sum:" + floatTot.ToString()); int[] myArray = new int[] {1,3,5,7,9}; Console.WriteLine("Return sum of array = {0}", cls.Sum(myArray).ToString()); }}The ref and out ParametersDid you ever need your method to return more than one value? You may need to do this occasionally, or you may need to use the same variables that you pass as an argument of the method. When you pass a reference type, such as a class instance, you don't have to worry about getting a value in a separate variable because the type is already being passed as a reference and will maintain the changes when it returns. A problem occurs when you want the value to be returned in the value type. The ref and out parameters help to do this with value types.The out keyword defines an out type parameter. You Use the out keyword to pass a parameter to a method. This example is passing an integer type variable as an out parameter. You define a function with the out keyword as an argument with the variable type:myMethod(out int iVal1)The out parameter can be used to return the values in the same variable passed as a parameter of the method. Any changes made to the parameter will be reflected in the variable. Listing 1-30 shows an example of the parameter.Listing 1-30. Using the out parameter
using System;public class myClass { public static void ReturnData(out int iVal1, out int iVal2) { iVal1 = 2; iVal2 = 5; } public static void Main() { int iV1, iV2; // variable need not be initialized ReturnData(out iV1, out iV2); Console.WriteLine(iV1); Console.WriteLine(iV2); }}The ref keyword defines a ref type parameter. You pass a parameter to a method with this keyword, as in listing 1-31. This example passes an integer type variable as a ref parameter. This is a method definition:myMethod(ref int iVal1)You can use the ref parameter as a method input parameter and an output parameter. Any changes made to the parameter will be reflected in the variable. See listing 1-31Listing 1-31. A ref parameter exampleusing System;public class myClass{ public static void ReturnData(ref int iVal1, ref int iVal2, ref int iVal3) { iVal1 += 2; iVal2 = iVal2 * iVal2; iVal3 = iVal2 + iVal1; } public static void Main() { int iV1, iV2, iV3; // variable need not be initialized iV1 = 3; iV2 = 10; iV3 = 1; ReturnData(ref iV1, ref iV2, ref iV3); Console.WriteLine(iV1); Console.WriteLine(iV2); Console.WriteLine(iV3); }}
In this method, ReturnData takes three values as input parameters, operates on the passed data returns the result in the same variable.PropertiesOther than methods, another important set of members of a class is variables. A variable is a type that stores some value. The property member of a class provides access to variables. Some examples of Properties are font type, color, and visible properties. Basically, Properties are fields. A field member can be accessed directly, but a property member is always accessed through accessor and modifier methods called get and set, respectively. If you have ever created active X controls in C++ or visual basic, or created javaBeans in java, you understand.Note: Visual Basic programmers will note that Let is not available in C# This is because all types are objects, so only the set access or is necessary.In Listing 1-32 you create two properties of myClass:Age and MaleGender. Age is an integer property, and MaleGender is a Boolean type property. As you can see in the example, the get and set keywords are used to get and set property values. You're reading and writing property values from the Main method. Note that leaving out the set method in a property makes the property read-only.Listing 1-32. Class property member exampleusing System;class myClass{ private bool bGender; private int intAge; // Gender property. public bool MaleGender { get { return bGender; } set { bGender = value; } } // Age property public int Age { get { return intAge; } set { intAge = value; } }}class TestmyClass{ static void Main() { myClass cls = new myClass(); // set properties values cls.MaleGender = true; cls.Age = 25; if (cls.MaleGender) { Console.WriteLine("The Gender is Male"); Console.WriteLine("Age is" + cls. Age.ToString() ); } }}
Why use properties if you already have the field available? First of all, properties expose fields in classes being used in components. They also provide a means for doing necessary computation before or after accessing or modifying the private fields they're representing. For example, if you're changing the color of a control in the set method, you may also want to execute an invalidate method inside the set to repaint the screen.EventsIn C# events are a special type of delegate. An event member of a class provides notifications from user or machine input.A class defines an event by providing an event declaration, which is of type delegate. The following line shows the definition of an event handler:public delegate void EventHandler(object sender, System.EventArgs e);The EventHandler takes two arguments: one of type object and the other of type System.EvenArgs. A class implements the event handler using the event keyword. In the following example, MyControl class implements the EventHandler:public class MyControl{public event EvenHandler Click; public void Reset() { Click = null; }}You probably know that Windows is an event- driven operating system. In Windows programming, the system sends messages to the massage queue for every action taken by a user or the system, such as mouse-click, keyboard, touch screen, and timers. Even if the operating system is doing nothing, it still sends an idle message to the message queue after a certain interval of time.Although you usually use events in GUI applications, you can also implement events in console-based application. You can use them when you need to notify a state of an action. You'll have a look at an example of both types.Listing 1-33 shows you how to implement events and event handlers in a console-based application. The Boiler.cs class defines the BoilerStatus event. The SetBoilerReading method sets the boiler temperature and pressure readings, and it writes the boiler status on the console based on the temperature and pressure reading. Boiler.cs defines BoilerStatus using the event keyword.Listing 1-33 Boiler.cs namespace BoilerEvent { using System; public class Boiler { public delegate void EngineHandler(int temp); public static event EngineHandler BoilerStatus; public Boiler() { } public void SetBoilerReading(int temp, int pressure) { if (BoilerStatus != null) { if (temp >=50 && pressure >= 60) { BoilerStatus(temp); Console.WriteLine("Boiler Status: Temperature High"); } else if (temp < 20 || pressure < 20) { BoilerStatus(temp); Console.WriteLine("Boiler status: Temperature Low"); } else Console.WriteLine("Boiler status: Temperature Normal"); } } }}Listing 1-34 is a caller class (main application) that calls the event through BoilerEventSink. The BoilerTempoMeter method of the sink generates a warning massage on the console only when the temperature of the boiler is zero.Listing 1-34. Caller of Boiler.Csnamespace BoilerEvent { using System; public class Boiler { // Boiler class here } public class BoilerEventSink { public void BoilerTempoMeter(int temp) { if (temp <= 0) { Console.WriteLine("Alarm: Boiler is switched off"); } } } // Event caller mailn application public class BoilerCallerApp { public static int Main(string [] args) { Boiler boiler1 = new Boiler(); BoilerEventSink bsink = new BoilerEventSink(); Boiler.BoilerStatus += new Boiler.EngineHandler( bsink.BoilerTempoMeter); boiler1.SetBoilerReadings (55, 74); boiler1.SetBoilerReadings (0, 54); boiler1.SetBoilerReadings (8, 23); return 0; } }}As you can see in Listing 1-34, I created a Boiler object that calls the BoilerStatus handler, which passes BoilerEventSink's methods as an argument when calling Boiler. EngineHandler is a delegate defined in the Boiler class. Then the program calls the SetBoilerReading method with different temperature and pressure reading. When the temperature is zero, the program displays a warning message on the console; otherwise, the program displays message generated by the SetBoilerReading method. Actually, it's easier to understand events using windows application than it is using a console-based application. To show you can an event sample in windows Forms, you'll create a Windows application. In this application, you'll create a form and a button. The button-click event executes and displays a message box. Here, the button-click event executes button1_click method:button1.Click += new System.EventHandler(button1_ Click);and the button-click handler looks like the following:private void button1_click(object sender, System.EventArgs e){MassageBox.Show ("button is clicked");}Listing 1-35 shows a windows forms program with event sample. If you compile this program, the out put looks like figure 1-8.Listing 1-35. Event Handling exampleusing System;using System.Windows.Forms;using System.Drawing;namespace NotePadWindowsForms{ public class NotePadWindowsForms: System.Windows.Forms.Form { private System.Windows.Forms.Button button1; public NotePadWindowsForms() { button1 = new System.Windows.Forms.Button(); // Button control and its properties button1.Location = new System.Drawing.Point(8, 32); button1.Name ="button1"; button1.Size = new System.Drawing.Size(104,32); button1.TabIndex = 0; button1.Text = "Click me"; // Adding controls to the form Controls.AddRange(new System.Windows.Forms.Control[] {button1} );button1.Click += new System.EventHandler(button1_Click); }// Button click handlerprivate void button1_Click(object sender, System.EventArgs e) { MessageBox.Show ("Button is clicked"); } public static int Main() { Application.Run(new NotePadWindowsForms()); return 0; } }}Figure 1-8 shows the output of listing 1-35 after clicking the Click me button.Figure 1-8 output of listing1-35IndexersIndexers are a new concept in C#. Indexers enable a class object to function as an array. Implementing indexers is similar to implementing properties using the get and set functions. The only different is that when you call an indexer, you pass an indexing parameter. Accessing an indexer is similar to accessing an array. Indexers are nameless, so the this keyword declares indexers.I just said that after defining indexers, a class object could be treated as an array. What does that mean? To explain, I'll show you an example using the class called my class. The way you treat an instance of myClass now is like this:myClass cls = new myClass();cls.MaleGender = true;After defining an indexer in myClass, you could treat an instance of it as if it were an array:myClass cls = new myClass();cls[0].MaleGender = true;cls[1].MaleGender = true;You define indexer by using the this keyword as if were an array property of type object. Listing 1-36 shows the indexer signature of my class.Listing 1-36. Indexers of myClass public object this[int index] { get { if (!ValidIndex(index)) throw new Exception("Index out of range."); else return MaleGender(index).Value; } set { if (!ValidIndex(index)) throw new Exception("Index out of range."); else MaleGender(index).Value = value; } }InheritanceInheritance is one of the main features of an object-oriented language. C# and the .NET class library are heavily based on inheritance. The telltale sign of this is that all .NET common library classes are derived from the object class, discussed at the beginning of this article. As pointed out, C# doesn't support multiple Inheritance. C# only supports single inheritance; therefore, all objects are implicitly derived from the object class.Implementing inheritance in C# is similar to implementing it in C++. You use a colon (:) in the definition of a class to derive it from another class. In listing1-37, BaseClassB, which later accesses the BaseClassA method in the Main method.Listing 1-37. Inheritance exampleusing System;// Base class Aclass BaseClassA{ public void MethodA() { Console.WriteLine("A Method called"); }}// Base class B is derived from Base class A class BaseClassB:BaseClassA{public void MethodB(){Console.WriteLine("B method called");}}class myClass{static void Main() {// Base class BBaseClassB b = new BaseClassB();// Base class B methodb.MethodB();// BaseClassA Method through BaseClassBb.MethodA();}}