.NET Languages

The common language runtime defines a common runtime for all .NET languages. Although C# and VB.NET are the two flagship languages of .NET, any language that targets the common language runtime is on equal footing with any other language. In this section we'll talk about the features that the .NET languages offer.

Classes and Objects

The common language runtime deals in managed types. The runtime can load types, execute methods of a type, and instantiate objects of a type. Although the common language runtime supports several forms of types, such as classes, interfaces, structures, enumerations, and delegates, all of these forms ultimately are represented as classes at the lowest levels of the runtime. And although the common language runtime does support exporting entry points that are not enclosed in a type, at least two languages (VB.NET and C#) do not support entry points outside of a type definition.

Although in OOP it is possible to invoke some class methods without objects, the most common use of classes is to produce objects. In the common language runtime, an object is an instance of exactly one class. The operations that may be performed on an object are determined by the object's class. The amount and type of storage used by the object is determined by the object's class. In essence, the class acts as a factory or template for objects that belong to that class.

The common language runtime supports instantiating objects based on a class. Each programming language exposes this functionality somewhat differently. In C# and VB.NET, for example, the new keyword is used to create a new object of a given class, as shown in the following two code snippets:

 IceCream ic = new IceCream(); ic.MakeACone(); 
 Dim ic as new IceCream(); ic.MakeACone () 

Classes are defined in C# and in VB.NET using the class keyword. The following code shows sample classes in each:

C# Class
 public class IceCream {     string strFlavor = "Chocolate";     public void MakeACone()     {        System.Console.Write( "I have made a cone. My flavor is " );         System.Console.WriteLine( strFlavor + "." );     } } 
VB.NET Class
 Public Class IceCream     Dim strFlavor as string = "Chocolate"     Public Sub MakeACone()        System.Console.Write("I have made a cone. My flavor is ")         System.Console.WriteLine(strFlavor & ".")     End Sub End Class 


By default, all class members are implicitly private and can be accessed only by methods of that class. This access can be made explicit using the private access modifier. Class members can be made accessible to all parties using the public access modifier, which informs the runtime that any party that can access the class can access this particular member. Class members can also be made accessible only when the assembly that contains the class is accessible. This is accomplished using the internal access modifier. Members marked internal can be accessed only by code that is compiled into the same assembly as the containing class. Table 1.3 shows the various protection keywords.

Table 1.3. The Protection Keywords







Type is visible everywhere




Type is only visible inside of assembly




Member is visible everywhere




Member is visible only inside of assembly




Member is visible only inside of declaring type




Member is visible to type and deriving type only


Unless the programmer takes special steps, the fields of the class will be set to a well-known initial value when an object is created. Numeric types are set to zero, and objects are set to null (C#) or Nothing (VB). You can change the values that are used by writing a constructor. A constructor is a special method that is called automatically to set the class's fields to a programmer-determined state prior to the first use of the object (or class).

Constructors are called when a new object is created, before the new operator returns the reference to the new object. Constructors may accept parameters, and they may be overloaded based on parameter count or type. The following code shows typical constructors:

 public class IceCream {      private int i = 5;      public IceCream()      {          System.Console.WriteLine( "This is delicious!" );      } } 
 Public Class IceCream      Sub New()         System.Console.WriteLine( "This is delicious!" )     End Sub End Class 


Namespaces in the .NET runtime are used to organize classes and types into separate spaces. You define namespaces using the namespace keyword, as shown in the following code:

 namespace Rick {     public class MyClass     {         public static void DoSomething()         {         }      } } 

The using keyword in C# promotes elements in other namespaces into the global namespace. The following code shows an example of referencing two separate namespaces with the using keyword:

 using Rick; using System; MyClass.DoSomething(); Console.WriteLine( "Just called DoSomething()" ); 

Interface Basics

An interface is a special kind of type in the common language runtime. Interfaces are used to partition the space of all possible objects into subcategories based on shared semantics. When two objects support the same interface, one can assume that the two objects share the functionality or behavior implied by the shared interface. A given object might support multiple interfaces, which implies that it belongs to multiple categories of objects.

Interface-based design was first popularized in component-based software engineering (such as COM and CORBA). Interface-based designs tend to express application constraints in a less implementation-specific manner than traditional class-based, object-oriented software engineering. In general, interface-based software is more extensible, maintainable, and easier to evolve than traditional class-based designs.

Part of a class definition is the list of supported interfaces. A given class may support as many interfaces as it wishes. Each language provides a syntax for expressing the list of supported interfaces. In C#, a class definition must list the interfaces it supports between the class name and the opening curly brace, as show in the following code:

 public interface IIceCream {     void TakeABite();     void AddSyrup(); } public class Sundae : IIceCream {     public void TakeABite()     {         // code goes here...     }     public void AddSyrup()     {         // Code goes here...     } } 

When a class supports an interface, instances of that class are acceptable anywhere a reference of the supported interfaces is allowed. This means that variables of a given class type may be passed where a supported interface type is expected.

Interfaces typically have one or more method declarations. When an interface contains a method declaration, all that is specified in the interface definition is the signature of the method; no actual executable code is provided in the interface definition. Rather, each class that supports the interface must provide its own implementation of that method signature that complies with the method's semantics as documented.

The method declarations that appear inside an interface definition are sometimes called abstract methods. Abstract methods are method declarations that must be supported in a derived class. If a given class does not provide an implementation of every method defined in every interface it claims to support, that class is itself abstract and cannot be used to instantiate objects.

Interfaces that have methods typically have several methods that work together in concert to define a protocol for interacting with objects of that type. The order of method invocation and acceptable parameter values often are documented as part of this protocol. To this end, interfaces act as useful fools for partitioning a software project into largely independent components.

Interfaces themselves can be marked as either public for inter-assembly use or internal for intra-assembly use. All methods of an interface must be public. In support of this requirement, it is illegal to use the public keyword inside of an interface definition.

Virtual Methods

The common language runtime supports two method-invocation mechanisms: virtual and non-virtual. With both mechanisms, the actual method invoked is based on type. In the case of non-virtual methods, the choice of implementation is based on the compile-time type of the variable expression used to invoke the method. In the case of virtual methods, the choice of implementation is based on the run-time type of the most-derived class of the object, independent of the compile-time type of the object reference used to invoke the method.

All abstract methods are also virtual. This means that all methods invoked via interface-based references are virtual. For example, because they are abstract, all methods declared in an interface are virtual.

Each language provides its own syntax for indicating that a method is virtual. In C#, methods declared in a class are virtual if they use either the abstract or virtual method modifiers. In VB.NET, methods declared in a class are virtual if they use either the MustOverride (wherein there is no default implementation) or Overridable (wherein there is a default implementation) method modifiers. A method declared as virtual/overridable must have a method implementation. However, a derived type is permitted to override the base class's implementation with one of its own.

When a derived class declares a method whose name and signature matches a method declared in a base class or interfaces, there is room for confusion. To keep the confusion to a minimum, the common language runtime requires the derived type to indicate its relationship to the base type's method declaration. The rules work differently depending on whether the base method declaration was virtual or non-virtual.

When a derived class declares a method whose name and signature matches a method declared as virtual or abstract in its base class, the derived class must indicate whether it is overriding the virtual method of the base or trying to introduce a new method. In C#, the derived method declaration must use the override method modifier. In VB.NET, the derived method declaration must use the override method modifier. The following code shows a C# class with a virtual method, and a derived class overriding the method:

     public class BaseClass {         public virtual void DoIt() {             Console.WriteLine( "In BaseClass.DoIt()" );         }     }     public class DerivedClass : BaseClass {         public override void DoIt() {             Console.WriteLine( "In DerivedClass.DoIt()" );         }     } BaseClass bc = new DerivedClass(); bc.DoIt(); // Writes "In DerivedClass.DoIt()" 


Each programming language provides its own constructs for defining properties. A property definition in C# looks like a hybrid of a field declaration with scoped method definitions. The following code shows a class with a property definition:

 public class IceCreamCone {     int m_nScoops;     public int Scoops     {         get { return m_nScoops; }         set { m_nAge = p.nScoops; }     } } // Using the property using System; IceCreamCone p = new IceCreamCone(); p.Scoops = 4; Console.WriteLine( p.Scoops ); 


Every language has its own way of allowing attributes to be applied. The following code shows how to apply attributes to a C# class:

  [ ShowInToolbox(true) ] public class ThisControl : WebControl {     private string text;     [ Bindable(true), DefaultValue("") ]     [ Category("Appearance") ]     public string Text     {         get { return text; }         set { text = Value; }     } } 


Exceptions are instances of classes that extend the System.Exception type either directly or indirectly. The common language runtime provides built-in exception types that extend System.Exception, System.ApplicationException, and System.SystemException. The following code shows how to catch an exception in C#:

 using System; using System.IO; public Class MyClass {     public static void Main()     {         try         {             File f( "C:\\SomeData.txt" );             f.Delete();         }         catch( DirectoryNotFoundException ex )         {             // This is a common exception for I/O.             Console.WriteLine( ex.Message );         }         catch( Exception ex )         {             // Here we catch all other exceptions.         }     } } 

ASP. NET Solutions - 24 Case Studies. Best Practices for Developers
ASP. NET Solutions - 24 Case Studies. Best Practices for Developers
ISBN: 321159659
Year: 2003
Pages: 175

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net