22
Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde C# and the .NET Framework Christoffer Sjöberg Daniel Sanfridsson Stefan Bygde Mälardalen University Mälardalen University Mälardalen University [email protected] [email protected] [email protected] Abstract The .NET framework is Microsoft’s attempt to create a platform that enables programmers to write platform independent code and at the same time tries to cut down development time, reduce possible bugs in code and increase safety in programs. This is made possible due to the fact that the .NET framework includes a runtime that automatically manages memory and provides type safety as well as gives the programmer access to a huge class library that includes everything from data collections such as vectors to various application specific classes. Since all languages wanting to work against the .NET platform are given a set of rules to comply to, language interoperability is reached, allowing classes and code written in one language to be used in another. At the same time as Microsoft developed the framework, they also developed a new language specifically designed to take advantage of the platform. With syntax similar to that of Java and C++, many programmers will find it familiar and easy to adapt to. However, new language constructs have also been added to C# that further aim to reduce common errors and speed up the building process, such as properties and delegates. The .Net framework is immense. This article will not attempt to describe all of the application specific tools that exists, but will describe the central parts of the framework and compare the C# language to its closest related object oriented languages, C++ and Java.

C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · [email protected] [email protected] [email protected] Abstract The .NET framework is Microsoft’s attempt

  • Upload
    others

  • View
    8

  • Download
    0

Embed Size (px)

Citation preview

Page 1: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

C# and the .NET Framework

Christoffer Sjöberg Daniel Sanfridsson Stefan Bygde Mälardalen University Mälardalen University Mälardalen University [email protected] [email protected] [email protected]

Abstract The .NET framework is Microsoft’s attempt to create a platform that enables programmers to write platform independent code and at the same time tries to cut down development time, reduce possible bugs in code and increase safety in programs. This is made possible due to the fact that the .NET framework includes a runtime that automatically manages memory and provides type safety as well as gives the programmer access to a huge class library that includes everything from data collections such as vectors to various application specific classes. Since all languages wanting to work against the .NET platform are given a set of rules to comply to, language interoperability is reached, allowing classes and code written in one language to be used in another. At the same time as Microsoft developed the framework, they also developed a new language specifically designed to take advantage of the platform. With syntax similar to that of Java and C++, many programmers will find it familiar and easy to adapt to. However, new language constructs have also been added to C# that further aim to reduce common errors and speed up the building process, such as properties and delegates. The .Net framework is immense. This article will not attempt to describe all of the application specific tools that exists, but will describe the central parts of the framework and compare the C# language to its closest related object oriented languages, C++ and Java.

Page 2: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

History and purpose of .NET and C# When the Internet usage exploded in the mid 90's Microsoft was initially caught off guard. By late 1999 it became clear that the area of Internet related applications was not only one among others, but actually essential for the future of the company. The company grasped that in times to come, much money could be made through the Internet and decided to not be left behind. The demand for shorter ”Time-to-Market”, with smaller releases and software updates over the Internet, would require changes to the development process and installing of additional software. Microsoft wanted to create a subscription model where customers pay for a 1-year license of a product. This would quell their fluctuating incomes and dampen the increasing problem of software piracy. The multitude of profit bringing web services and Internet commerce would further more demand higher safety and more flexible solutions. More traditional applications will also be depending on the Internet, in one way or the other, and many will become distributed and interact with other applications on different platforms. All of the listed areas called for more secure, standardized and easier solutions to version handling, installation procedures, graphics, XML services and cross- language and platform programming. In an attempt to conquer the Internet market the .NET framework was created. To be able to enjoy the benefits of the new framework an object-oriented language was needed that would be a reflection of the underlying framework. Microsoft wanted a modern language that should be easy to learn and powerful to use. It should have C-based syntax but still leave C behind. It had to be a pure object-oriented language and be less error prone than its ancestors, in order to support rapid development. The language created became C#, pronounced C sharp, and a declaration of intent states that: C# ”...combines the power of C++ with productivity of VB and elegance of Java.” [1]

Why use the .NET framework The .NET framework is a programming environment for multiple languages, that Microsoft claims will improve performance, reliability and security. A benefit of the framework is that a programmer can use the same tools, regardless if he/she is programming a web application, windows program or mobile service. A central part of the framework is the immense object oriented class library that assists a developer in different situation, such as database access, user interfaces, web applications and much more. With the .NET framework it is possible to develop software in a consistent way. Outside .NET many similar or complementary techniques have existed for various applications. As an example, database access can be done by the use of techniques like ADO, DAO and RDO. In the framework the same task is accomplished with one technique named ADO.NET.

Page 3: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Furthermore, there have been problems with versioning and DLL conflicts in Windows. In the past, using code from different languages has been a hard nut, due to incompatible types of the languages and the need of language describing IDL-files (Interface Definition Language). Microsoft claims that .NET puts an end to the so-called ”DLL-hell”. If the framework is installed, and an application is running on one computer, it will also run on another, regardless of earlier installed DLL files (Dynamic Link Library). This is possible since all information that your application will need, will be stored together with the code in what is called an assembly. The Windows registry need not be used for registering programs. If all files are just put in the right directory, there should be no problems for the application to run. The framework today supports around 20 programming languages. And one of the most significant aspects of .NET is that all languages, that are supported, will be able to communicate without obstacles. That means that if you implement a function in for instance Visual Basic, you will be able to call it from a C# program.

Understanding the basics of .NET The .NET platform can be divided into two main parts, a runtime known as the Common Language Runtime (CLR) and a huge class library. All code, compiled from the languages supported by the .NET platform will run inside the CLR and will thus have automatic memory management, increased security and type safety. The runtime does not use native machine code, but an intermediate language named MSIL. All the .NET languages compile to MSIL, therefore the platform can support multiple programming languages. In order to make this work the runtime enforces a set of rules on types called the Common Type System, which the languages needs to comply to for the language interoperability to work. The class library is a huge collection of code, actually about 4000 classes which add support for input and output, file handling, string handling, networking, thread management, data collections etc. It can be compared to the base library of Java, but it is more extensive. On top of these classes there is additional technology for handling data in most popular databases as well as XML support. A lot of work has also been put into the Windows Forms classes, which aim to make development of GUI applications as easy as they are in Visual Basic.

From code to running program When one compiles code written for the .NET framework one does not get an executable file containing machine code. Instead something called an assembly is created with code in a platform and CPU-independent intermediate language called MSIL. The file containing MSIL code is a binary format that is portable to any platform. This code is later executed by the Common Language Runtime and is compiled to machine code during runtime, as different parts of the program are needed. This is performed by the Just-In-Time compiler (JIT).

Page 4: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Language interoperability In order for language interoperability to work, there is a set of rules called the Common Language Specification, which can be seen as a smallest common denominator that programming languages must support in order to be .NET compliant. While some languages might have a hard time to live up to these rules, others like C++ have had to be constrained in order to support the CLS. To assist the programmer in determining if his code supports interoperability the framework provides the [CLSCompliant] attribute. It can be set to notify the compiler that you want it to check if the code is compliant and issue errors for any deviations. The following picture shows how the parts come together to form the .NET platform.

Going deeper into the framework

Just In Time Compilation (JIT) A program that is executed for the first time on a system will need to be compiled into native code specific for the machine. The code is compiled only when it is needed (hence Just-In-Time) and the resulting machine code is cached in memory by the runtime. This ensures that there is only a performance impact when a function is used for the first time. Since the JIT compiler does the translation to native code on the system it is installed on, it can also do optimisations for the system, which improves performance. A system can also provide different JIT compilers; there are compilers for systems where memory is sparse and therefore compiled code isn't cached. Conversely there exist JIT compilers that pre-build the entire program in order to improve performance.

Page 5: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Platform Independence Since the JIT performs the translation to native machine code, any platform supporting the .NET runtime and a JIT can use the same binary produced in the first compilation to MSIL code. Thus true platform independence is achieved without having to compile the code more than once for any number of platforms and system architectures. As Microsoft has only provided the tools for using .NET with the Windows platform there are other actors working on creating support for other platforms. One is the open source project Mono, which aims to deliver .NET support for the Linux operating system.

Common Type System (CTS) The common type system defines how types should be defined in order for different languages to be able to share code, this would not be possible i.e. if one language thought of integers as 16bit while another considered them 64bit.

Common Language Runtime (CLR) The CLR manages the execution of code written against the .NET framework in a number of ways. It has a garbage collector, which automatically frees memory associated to managed (runtime controlled) data that are no longer in use by the application, to reduce the problem of memory leaks. The programmer has no control over when the garbage collector will deallocate the memory since it runs in a separate thread of the runtime. By default all data is considered managed, however the framework also allows the programmer to define data as unmanaged and as such can program exactly when an object is to be freed, in a similar way as coding in C++. This empowers code written for .NET with the strengths of both C++ and Java's memory handling. The runtime also manages security and resources that the application uses. The metadata for each assembly provides information of exactly what versions of its resources it is dependent upon, as well as the hashes for them to ensure that no files are tampered with e.g. by a hacker or virus.

Garbage Collection When the program needs to allocate memory the runtime does so on what is called a managed heap, where all reference types are stored. The objects are all stored in this memory area one after each other. At the same time the object is created, it is also added to the applications roots, which is a tree-like system of pointers for the objects that the application is using. When later on the garbage collector has deemed the time suitable for a garbage collection, the roots of the application are traversed creating a graph of reachable objects. Any objects that are no longer reachable from the application will be freed. Data is removed through a memory copy that moves all data after the unused memory back one step on the heap and the necessary pointers are adjusted. This procedure is called compacting. If this technique was to be applied to larger data objects there would be a significant performance impact [5], which is why they are stored on a separate heap where they are simply removed without any following compacting.

Page 6: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Generations In reality the garbage collector has been optimised using observations of garbage collecting technologies and uses a system that divides the managed heap into generations, which has a fixed number of data it can reference. Each newly allocated memory is considered part of generation 0. Garbage collection is triggered when one of the generations are full, and is limited to work on this set. After the first garbage collection the data that survives are promoted to the next generation. This system reduces the frequency the garbage collector needs to be run, as well as the size of memory that needs compacting.

Focusing on the Common Type System The type system declares a hierarchy of types with System.Object as the base class for all run-time classes. All types inherit from Object, even types that do not directly support inheritance. Types are divided in two subgroups: value types and reference types.

Value Types Value types include structures, primitive types and enumerations. They are always allocated on the stack and represent their data as binary representations of the values. All value types inherit indirectly from System.ValueType and must be boxed (a technique that will be described later), to enjoy inheritance from Object. Value types are sealed, which means that they cannot be inherited from. Copying, assigning and parameter passing creates a copy of the value for each member in the type. Value types therefore produce clean copies and clones do not affect each other.

Page 7: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Structures A struct can have fields, methods, events and nested members. It can implement multiple interfaces and indirectly inherits virtual methods from System.ValueType. It can have constructors and visibility attributes like public and private. Moreover, they can implement interfaces and override virtual methods from the base hierarchy. It cannot be derived from or inherit from any base class except indirectly from the class mentioned. Structures are lightweight objects that are, in some situations, more effective than classes and avoids the overhead needed for instantiating a class. A struct can never be null due to its allocation on the stack.

Primitive Types Primitive types as in C++ or Java, do actually not exist, instead they are structs. This includes types such as int and char. It might not seem to be memory efficient to implement primitive types as structs. But since they only store their values as a struct with one data member, it will take as much place in memory and will be represented in the same binary way as an ordinary basic type. Advantages of this solution are that in the struct for every primitive type methods for conversions, unary and binary operations can be stored. Since structs also may implement interfaces this generalizes and creates a contract for how types may be used. No exceptions are thereby made for primitive types and they will also benefit from Object inheritance.

Enumerations The underlying type of an enumeration can be of any primitive integer type. Members with different names can have the same value. They inherit from System.Enum and can be boxed and use inherited methods. They are the most restricted of all types. They cannot implement interfaces or define their own methods. Since the members of an enumeration are connected to the enumeration, the same member name can be used in different enumerations without collision, if the language supports it.

Reference Types

Classes Classes in .NET only support single inheritance, not counting the type specific subclass that a class inherits from. But they may implement multiple interfaces. Their members may for example be fields, methods, events, properties or nested members. These can have a broad variety of modifiers that among others defines visibility modes. Modifiers may also be used on class basis. Inheritance is always public, which means that a derived class inherits all of the base class members that may be inherited. Base class methods can be used, hidden or overridden. Methods can be virtual and use polymorphism.

Interfaces Interfaces may include static fields, virtual and abstract methods, nested types and events. They can have visibility modifiers but their methods must be public. A class that implements multiple

Page 8: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

interfaces with colliding members may implement unique methods for each and every one of them.

Delegates Delegates are best described as a more general function pointer. They are actually classes but may conceptually be described as a list of functions that will be invoked when the delegate is invoked. Functions can be added or removed and must share the exact signatures as the delegate. Delegates can reference both static and instance methods. Delegates will be discussed more thoroughly under new language constructs.

Arrays All arrays inherit from the important System.Array. This base class has a number of fields such as total Length, Rank (number of dimensions) and IsReadOnly, where information on an array is stored. It also has a number of methods for indexing, searching, getting the rank and length. An interesting method is CreateInstance() that makes it possible to dynamically create an array instance from an existing one. Internally an array is a number of memory locations specified by its length and rank and can only contain members of the declared type.

Pointers Three different pointers are supported by the runtime system; one of them ensures language interoperability. That one is the managed pointer. It is a pointer to a memory area in a managed block of memory on the heap that will be garbage collected. This pointer supports loading and storing of a value from the address of the pointer. It does not support any operations for changing the actual address contained by the pointer. In addition there is the unmanaged pointer, which can be described as a traditional C-pointer and the unmanaged function pointer. Unmanaged pointers are accessible also in C#. By using the keyword unsafe on the blocks that uses them pointers can be used in C fashion. When a compiler analyses and converts the user program to MSIL-code and metadata it translates language constructs to the types represented in the Common Type System. An important concept in the framework is metadata, which will be further described together with assemblies. Language compilers store implementation in MSIL together with metadata for each type in a language neutral way. The metadata describes the types enough to reproduce them. This removes the need of additional type and language describing files.

Understanding Assemblies When compiling C# code, either if it's a program or a DLL, it is compiled into something called an assembly. The assembly contains the compiled code and resources, such as graphics and icons, as well as something called metadata. In the case of single-file assemblies all these parts of the program are put together in a single file. There is also the possibility to create multi-file

Page 9: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

assemblies in which the parts of the program are separated into several files. The differences between the two types of assemblies are illustrated by the following graphic:

The metadata makes the assembly self-describing in the way that it describes the code contained in the assembly. First there is the assembly metadata, which is known as the manifest. This data structure contains the following:

• The identity of the assembly, which consists of its name/title, version, culture (if provided), which company created the assembly and a strong name, which is used for shared assemblies, more on that later.

• The names of the included files in the assembly as well as their hashes, which adds to the security of the assembly since a hacker is unable to insert malicious code e.g. a virus into the assembly.

• References to what other assemblies this assembly uses, along with their hashes. After the manifest follows the type metadata, which includes information on the classes/types included, their methods with their return values, parameters and visibility modifiers, as well as the attributes of the class. This metadata allows other languages to use the classes contained in the assembly as long as they support the common language structure (CLS).

Private and Public Assemblies An assembly is automatically created as a private assembly, which means that it can only be used by a program within the same directory. If other programs want to use the same assembly another copy of it needs to be created in that programs directory. However it is also possible to create public assemblies that can reside in what is known as the Global Assembly Cache. Assemblies here are shared across the system, so programs that use the same assembly don't require separate copies. In order to be able to add an assembly to the global assembly cache the assembly needs to have a strong name, which consists of the name, version and culture of the assembly, as well as a public key and digital signature. This provides extra security as well as ensures that there are no version conflicts as assemblies with the same name but different signatures are considered different.

Page 10: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Since the assembly already contains information on its version it is no longer required to store that information in the registry as the case was with previous shared DLL technologies such as COM. The assembly itself knows its version as well as what versions of other assemblies it requires. Through a technology named side-by-side execution different versions of the same assembly can be used at the same time in the system without conflicts.

Attributes, controlling the Runtime In addition to the manifest and type metadata there exists a third category of metadata called attributes, some of which the .NET framework provides. The programmer is also free to define his own attributes. Attributes are used to describe the code to the runtime environment. For instance the assembly metadata such as title is in fact an attribute provided from the .NET framework and appears like this if you examine the created assembly: [Assembly: AssemblyTitle(“Name here”)]

The first part Assembly: defines the target of the attribute, in this case the attribute is valid for the whole assembly. Other targets are Class, Method, ReturnValue etc. The second part appears similar to a constructor, and this is exactly what it is. Attributes are in fact classes that appear in the assembly and are analysed by the runtime. The attribute name used here is actually short for AssemblyTitleAttribute, but C# has the ability to use both the shortened and full name.

Examples of Attributes Some highlights of the provided attributes are System.Diagnostics.TestConditional, which can take the role of #ifdef from C++ in the way that it can control whether code should be called or not depending on the conditional test. For instance a C# compiler automatically defines the conditional “Debug” which one could use to only make certain functionality appear when running a debug build of a program. Another interesting attribute is System.ObsoleteAttribute. When defined for a method in an assembly a programmer trying to use the method will receive a warning that it has been marked as obsolete and a reference to another method that has superseded it. If the assembly programmer chooses to, an error instead of a warning can be produced and the one using the assembly is then forced to update his program and use the improved method in the assembly. A last attribute worth mentioning is System.SerializableAttribute, which can be used in conjunction with classes to easily provide a way to save an object to a byte stream and into a file. Simply adding [Serializable] before a class definition provides this functionality. As previously noted the programmer can also create his own attributes by defining classes that inherit from the System.Attribute class. He also needs to define the possible targets of his new attributes through the AttributeUsageAttribute. Through this construct one could define attributes for simply saving comment inside the assembly (since standard comments are stripped

Page 11: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

out) or provide functionality to first create a table inside a database to enable the saving of objects into the database.

C#, a reflection of the framework After the brief description of the gigantic .NET framework we will now move on and introduce you to one of the most recently created object oriented languages. The language is C# and was created for modern software development based on .NET. C# has, just like its closest relatives Java and C++, inherited its basic language constructs and syntax from C. In the matter of syntax they are all in the same C-family. All of the language designers have tried to improve and change criticised issues or add new improved features to the earlier languages, C# included. Most of the new constructs are minor, and will be discussed briefly or omitted. However some are of importance and introduce new approaches to the developer. At a glance one notices that the dot syntax for method invoking on classes can be used on all types in the language. Some new keywords are safe, unsafe, decimal, byte, foreach, params, ref, out and some more. Otherwise the language looks like a combination of Java and C++. One should remember that C# is not a standalone language with its own type- and run-time system. It is design for, and based on .NET as its foundation. Its types for example are nothing else than aliases for the underlying primitives in the framework. Before contrasting the language in the light of Java and C++ some new features in C# will be highlighted.

New language constructs

Properties C# offers a new language construct to speed up the access of field members and the implementation of get, set methods. It allows class members to be accessed by their name, often capitalized. An expression like instance.Field will invoke the get or set method depending on the circumstances.

Foreach Is a construct that derives from Visual Basic and can be used to traverse all elements in an array. This is possible since an array is a class and knows its length. Its purpose is to avoid out of range errors for array traverses. Example: // Print all strings in the array

foreach(string s in anArray) { Writeln(s); }

Page 12: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Ref and out Value types are always passed by value. To pass them by reference ref alternately out shall be used both on the formal and actual parameter. Keyword out is an explicit way to indicate that the variable will receive its value from the method and may be uninitialised. It can be used to show a return by parameter. Otherwise it behaves just like ref. These keywords can also be used on reference types to achieve a managed pointer to pointer.

Params A flexible construction is params that support a variable number of arguments. This construction has its counterpart in ellipses from C++, which is not type specific and therefore not typesafe. By using the keyword params in front of the last type in a formal parameter list, a variable number of arguments of the same type may follow.

New Someone may wonder why the keyword new is mentioned under new language constructs. The reason is due to its changed functionality from new in C++. Keyword new can be used on both reference and value types, including primitive types. Calling new on a reference type will result in an allocation from the heap, as expected. However, calling new on a value type will cause a stack allocation. Since the heap is garbage collected no delete keyword is available. A developer that needs to control when memory is deallocated, can control the garbage collector to some extent by implementing an interface called IDisposable.

Delegates Are actually derived from the framework and is best described as generalized C++ function pointers. They can be used in pretty much the same situations as function pointers are used. However they have some important features in contrast to function pointers. Initially they are typesafe. Secondly they can have visibility attributes, private, public etc. The strength of privately declared delegates will be described in an example: In many situations classes want to change their state when something happens. By using the Observer pattern it is possible to define a relation between Observers and a class Observable in a very general way. The Observers need to implement a function called Update(), which is invoked every time the controlling Observable derived class makes a Notify(). Even though this is a general solution it has a drawback. Methods from an interface have to be public. Therefore anyone with a reference to an Observer object can call the Update() method, possibly breaking the synchronization between Observer/Observable. Private delegates solve this dilemma. Delegates can also reference both static and instance methods in contrast to function pointers. The reason is that a delegate actually is a class that stores a reference to both a class instance and a method. For static methods the class instance reference is null. A delegate can have a reference to another delegate and thereby be connected into a list of delegates that is invoked when the

Page 13: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

delegate is invoked. The concept is named multicast delegate and is frequently used in the .NET framework for callback functions and event handlers.

C# in the light of its ancestors ”There are disadvantages in being very young: You don’t get much respect, and you have to go to school. But there are some advantages: You can learn from other’s mistakes if you pay attention, and you don’t have to pay taxes.” [2] To give the reader a chance to get intimate with this new language it will be described and compared to Java and C++. This will not be an extensive description of the language neither will it be a very detailed comparison. The intention is to point out some important areas and features and compare these to Java and C++.

Inheritance from Object A criterion for a subtype is that it can replace its base type at all occasions. By using polymorphism, the possibility for something to appear in different shapes at different circumstances, subtypes can benefit from implementation that accepts its base type. By having a common base class the language can offer functionality and structure for its subtypes. Java and C# both have chosen a common base class at the top of the class hierarchy, C++ has not. Some claim that a language cannot be fully object oriented without a common base class. As always when using inheritance or implementation of interfaces properly, it categorizes and clarifies the use of its types. A common base class sets up some standards and offers the possibility to look at all classes in the same way when needed. By using this approach it is possible to construct general classes with methods that takes or returns a parameter of the type common base class. These methods can then be used by all classes without the need of other language constructs. The common base class is called Object in Java and Object, alias System.Object in C#. How ever general this technique may seem it also has a backside. If all items in a collection are Objects we may not know its most derived type. To support the programmer runtime control for type checking and error handling is supported by both languages, if wanted. General constructs can of course be achieved in C++ by the use of templates and pointers to void. The ease of use and the use of polymorphism might be considered more object-oriented by some people. This may speak for collections with objects. Execution speed due to less overhead and predefined type of the template instance is something that speaks for templates. Execution speed and also the possibility to make completely different and multiple hierarchies are advantages in C++ choice of not creating a common base class.

Boxing/Unboxing Both Java and C# provide collections like lists and other abstract data types which only store subtypes of Object. Java solves the problem of storing primitive types by adding wrapper classes

Page 14: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

in the class hierarchy for them. When a primitive type is to be inserted into a collection, the programmer creates an instance of the types corresponding wrapper class by giving the value to the constructor. To reverse the process from Object to primitive type, a downcast from Object to wrapper class is performed. The programmer then invokes a method that returns the value. C# takes the inheritance from Object one step further by letting all types including value types indirectly inherit from Object. Value types only inherit indirectly from its base class. At occasions where a primitive type needs to be treated as objects such as when invoking overridden methods or when an assignment from value type to object type occurs, an implicit encapsulation is performed. This implicit technique is called boxing. For every value type created, the runtime system will make a corresponding, type specific boxing class available. And when a value type needs to appear as a subtype of Object the boxing class is used in place of the value type. Assignment in the opposite direction, from boxing class to value type is called unboxing. Notice that the primitive type and the boxing class coexist and that changes performed on either one will not affect the other unless an unboxing is performed eventually. This can produce unwanted side effects for the unwary. The boxing technique is conceptually very much alike the Java wrapping model but C# converts implicitly when Java does it explicitly.

Inheritance in C# Inheritance in C# is similar to that in Java. Multiple inheritance is supported only for interfaces. That is due to some problems that may occur when using multiple inheritance. Problems such as conflicts when a subclass inherits from two classes that share the same base class. This would mean that the subclass would inherit two times from that base class, which will lead to conflicts. These problems are not unsolvable but one needs to know about the class hierarchy to do this. The removal of multiple inheritance is, of course, a restriction in the language, but the idea is probably to reduce as many errors as possible. In C#, unlike Java, there is no difference in syntax when inheriting from a class or an interface, the only requirement is that if a class is inherited, it has to be declared first as in the following example: Class class : c1, i1, i2 // where c1 is a class and i1, i2 are

interfaces.

To distinguish between interfaces and classes Microsoft recommends that interfaces shall be preceeded by a capital I, as in IEnumerable.

Polymorphism In C# all classes are reference types, which simplifies polymorphic behaviour. Hence the slicing effect that may occur on statically declared classes in for instance C++ will not occur.

Page 15: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

In C#, unlike Java, dynamic binding is not default. When overriding a method in a base class, it has to be declared as virtual, as in C++. The idea is that the one who implements a class has to decide whether a method may be overridden. Java has dynamic binding as default. So to disallow overriding of a method, it has to be declared as final. Further on it is possible to “hide” a non-virtual method. If one tries to declare a method with the same name and exact signature, as a non-virtual method in the base class, the result will be a warning from the compiler. This means that if a method should be hidden the compiler must be explicitly told so, by declaring it as new. A method declared as new will not be using dynamic binding. When overriding a method it has to be explicitly declared with the keyword override to indicate that this method overrides a virtual method. There is however no need to use the virtual keyword again in a deeper subclass, a method with the modifier override is of course also virtual.

Abstract Base Classes Abstract base classes must be declared with the keyword abstract and means that no instances of the class can be created. Abstract methods also have to be declared with the abstract keyword. If any method is declared with abstract, the whole class has to be abstract. C# also permits a programmer to seal a class, so that it cannot be subclassed. If a class is declared with the keyword sealed, an attempt to make a subclass of it will result in a compiler error. The sealed keyword can of course not be applied to interfaces. This functionality is available in Java as well, with the keyword final. Further on, the sealed keyword can also be used on methods to indicate that they cannot be overridden.

Visibility in inheritance In C++ one can use access modifiers in inheritance. This is not possible in C#, because it ruins the principle of substitutability. The principle of substitution says that if we have an instance of a subtype can be used in any context that an instance of a supertype can. This means that inheritance for construction has no direct support though it can be achieved by changing the visibility of a method within the class. Instead every class can have an access modifier like public, protected etc. C# provides some more access modifiers like internal that is used when a class can only be used within the same assembly. A private class will not provide any implementation to a subclass.

Operator overloading Just like functions can be overloaded, so can operators. This construct allows the programmer to use operators like + and - between classes he has defined, just as he would between integers. Both C# and C++ supports this overloading mechanism, Java does not. There are three different types of operators that can be overloaded: Unary operators, take one parameter, binary operators, take two parameters and classes that want to support the interface IComparable must implement comparison operators. Subtypes from IConvertable have

Page 16: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

operators that can be called when the programmer implicitly or explicitly try to convert an object to another class. The operators that can be overloaded are: Unary operators: +, -, !, ~, ++, --, true, false Binary operators: +, -, *, /, %, &, |, ^, <<, >> Comparison operators: ==, !=, >, <, >=, <= Conversion operators can be defined as either implicit or explicit. In contrast to C++ the indexing operator [] is not included here, because it has been replaced by a construct named Indexer in C#. It’s worth noting that the compounded operators such as += don’t need overloading if + already has been defined for the class. Also when defining the comparison operators you need to do so in pairs, so that if you overload the == operator you are also required to define !=, similarly < and > works as a pair, as does <= and =>. All operators that are overloaded need to be made public static in C#. This is in contrast to how operator overloading was done in C++, where polymorphic behaviour was supported on one of the arguments. The operator overloading construct does not add anything to the capabilities of the language and the opinions on whether the readability of code is made easier or not. This is one of the reasons Java so far doesn’t include the ability, however it may still be included in the future: “Overloaded operators are still a subject of controversy. They are almost indispensable for certain kinds of mathematical work, but people who oppose adding them to the Java language point out, quite rightly, that the feature was badly abused in C++ for nonmathematical purposes, making code much harder to read than necessary.” [3]

Runtime information C# or more correctly .NET has an extensive built in support for runtime information on metadata. This powerful feature enables a developer to write programs that can build or reconstruct classes dynamically. Programming using metadata is called reflecting and is supported also in Java. Sometimes, even though it should seldom be necessary in a good design, there is a need to know which type of object you are dealing with in an inheritance hierarchy. C# provides a way to determine the runtime type of the object, by using the is operator, which returns a boolean value when asked if an object is a type. Example: if(obj is IWriteable) ...

To cast an object the operator as can be used. Example: IWriteable s = obj as IWriteable.

Page 17: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

If the cast does not succeed, then s will be set to null. The is operator corresponds to the instanceof operator in Java and the as operator is similar to the dynamic_cast operator in C++;

Namespaces Namespaces provide the ability to organize classes of related functionality into a hierarchy. This construct is the same in C# as in C++, however Java’s packages do not function entirely in the same way. Java ties this hierarchy down to how files are organized in the file system, while C# and C++ separates the physical and logical hierarchies. The purpose of namespaces/packages is to be able to differentiate classes with similar name, but different functionality. For instance one could define a class Point in a namespace TwoD for handling a location in 2D and still define a class with the same name in namespace ThreeD for handling 3D coordinates. When coding in C# without the use of namespaces classes are inserted into a global namespace and all are accessed as the programmer is used to. However if a class is moved into a namespace the programmer needs to use the fully qualified name to access it from outside the namespace (classes in the same namespace can access other classes as usual), like: MyNamespace.MyClass mc = new MyNamespace.MyClass();

If the functionality contained in the namespace is often used, this adds a lot to the typing when coding, which is why there is a directive using (dubbed import in Java) which allows the programmer to import the names contained in the namespace for easier access. MyClass contained in the namespace MyNamespace can hence be accessed easier as: using MyNamespace; // first import the name

MyClass mc = new MyClass(); // easier access

The using directive can also be used to create aliases for easy access to functionality inside a namespace, a feature not found in Java. Given the following nestled namespace hierarchy: namespace SpaceOne {

namespace SpaceTwo {

Class Hidden {

// Implementation here

} } }

It is possibly to access the class Hidden by making an alias to the containing namespace:

Page 18: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

using s_two = SpaceOne.SpaceTwo;

s_two.Hidden hidden = new s_two.Hidden();

Exception Handling Exception handling in C# has the same syntax as Java. Exceptions that occur inside a try block can be handled by a catch block. A try block has to be followed by either a catch block or a finally block. The finally block is always executed regardless if an exception occurred or not and can be used for housekeeping tasks, such as destroying objects, closing files etc. A good property of .NET's exceptions are the ways that can be used to trace from where the exception was thrown. When an exception occurs, a StackTrace object can be created inside the exception handler which will hold information about the application, method and row number from where the exception was thrown. It is also possible to generate custom exceptions, derived from the applicationException class. Both Java and C# use extensive exception handling. In contrast to C++, attempts to reference null or pass an array bound or perform a type conversion that is not supported will always result in an exception. Since exceptions are generated by the runtime, all code running under .NET can benefit from consistent exception handling regardless of the language. In C# unlike both C++ and Java, there are no throw lists allowed on methods. Throw lists are a way for the programmer to determine what exceptions he/she wants to catch. In Java, throw lists are required for all exceptions, except those in the category run-time exceptions while in C++ they are optional. There is a problem not allowing throw lists: if documentation is missing there is no easy way for the client to know what exceptions a method throws, except analysing the code. In C# it is not required for the programmer to try to catch all exceptions. If the programmer doesn't catch it, then the CLR will. An interesting functionality provided by C# is exception wrapping. If you catch an exception, instead of rethrowing it, you can wrap it up in another exception. The advantage with this construct is that you can throw a more specific exception once you have caught it, maybe with more information about the problem. The first thrown exception will still be available within the new exception through the property InnerException. But only the outer exception can be matched in a catch block.

Typesafety The reason why exceptions are not generated on many strange type conversions in C++ is due to its very loose pointer restrictions. Java and C# has another view on this issue also known as typesafety. Typesafety is a concept that occurs in many comparisons between C++, Java and C#. A short definition of typesafety will therefore be given: ”A language is type-safe if the only operations that can be performed on data in the language are those sanctioned by the type of the data.” [2]

Page 19: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

A language can handle errors by detecting them or not. Detected type errors can be ignored, generate a compiler error, make reports by return values or result in an exception. Some language constructs are unsafe because it is not always possible to perform a type check, or the language considers the unsafe conversion perfectly legal, as the case is with traditional pointers in C++. Other constructs are unsafe since they give the programmer the freedom to shut off type control. ”C-style cast is neither safe nor explicit enough. It disables the compiler's type safety checks;” [4] The languages in focus have made different approaches to typesafety. C++ is C compatible and thereby allows type unsafe pointers and casts. Safer type conversions are available, like the dynamic_cast operation. It should of course be used in C++ when dealing with type conversions on classes. Both Java and C# were designed to be typesafe and thereby reduces error due to type misuses. Illegal casts and other type errors will generate a compiler error or an exception in both Java and C#. Truncation errors on the value are still possible on primitive types if an explicit type conversion is used. C# has language construct for checked or unchecked blocks. A checked block will throw exceptions on arithmetic overflow. Moreover, C# compiler doesn't allow variables to be used if they are uninitialised. This will result in a compiler error. The purpose is to remove common programming bugs with sometimes cryptic run-time errors. ”It seems as if Java was built to keep a developer from shooting himself in the foot. It seems as if C# was built to give the developer a gun but leave the safety turned on. And it seems as if when C++ was built, they just handed the programmer a fully-loaded bazooka with an open-ended license to use it.” [2]

Conclusion Microsoft's .NET is a new framework for object-oriented software development. At its heart is the Common Type System that is a class hierarchy, with System.Object on the top, from which all types are derived. Language builders may, by following a Common Language Specification, implement a compiler that translates their language to an intermediate code called MSIL. The types of the source language are stored as the types specified in the CTS, in a representation called metadata, together with the code in an assembly. The assembly includes everything that is needed to execute the application, thereby removing the problems with DLL versioning files. Since both MSIL code and metadata are language independent, languages are represented in the same way and can interact without any additional techniques. Assemblies have different security attributes depending of the kind of application; therefore code running on the Internet can be denied access to unwanted parts of the local computer. When an application is to be executed on a native system it will be compiled by a platform specific Just-In-Time compiler to machine code, as the code sequence is needed. In addition to the described core of the .NET there is an extensive class library that supports many application specific tools and commonly used data types. The framework was designed for a more consistent, easier and safer relation to the Internet.

Page 20: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Together with .NET framework, Microsoft presented a new language named C#. It is object oriented, typesafe and is in the same family as Java and C++. It is easy to learn and supports rapid development by changing or removing some error prone constructions inherited from C and adding new ones like foreach and delegates. It has broader language features than Java and it handles errors in an equally consistent way by the use of exceptions. C# is dependent on the framework, where from its types and garbage collected memory handling derive.

Discussion: Choosing language and environment We will try to give an indication on when it might be appropriate to choose a language or an environment. What one environment should choose depends on the application to be built.

Real-time applications When an application has real-time constraints and needs predictable or fast execution time, neither Java nor the .NET framework are well suited due to their interpretation and garbage collecting. C++ is a better choice.

Platform independent When an application needs to run on different platforms the language best suited today is Java, which can run on a multitude of platforms. However the intermediate representation within .NET framework makes it fully platform independent. A language or platform builder is free to implement a JIT-compiler for the specific platform, by following some rules. The platforms currently supported are modern Windows OS's/x86. But as mentioned before there is an open source .NET implementation called Mono that targets Linux/x86, with SPARC and Solaris versions on the way. So in the years to come .NET has potential to be as platform independent as Java is today and meanwhile the platforms already working will be sufficient for many applications. One should not forget that not even Java runs on all platforms.

Depending on written code Systems that rely heavily on already written code cannot easily be ported to the .NET framework. Making code CLS compliant and thereby restricting it to the .NET framework takes a lot of effort if the code is already written. When plenty of code is written in C++ for example, all traditional pointers has to be removed, if the code is to be able to run under .NET. It is even worse if the main part of the system is written in a purely procedural language. However you can choose to use traditional inter-language communication techniques and thereby keep some of the code outside the framework.

Using .NET As stated many times before the .NET framework is a powerful tool for writing truly object-oriented, typesafe applications in different languages that can run on different platforms. It has extensive development environments and a window handling that Microsoft claims is as easy as

Page 21: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

Visual Basics. It has a huge class library with well-documented, advanced features that are relatively easy to use, has high-level threads, XML support and safety for web applications etc.

Languages When building applications in the framework, the choice of language is a matter of personal taste of the developer. Compilers are today available for languages such as C#, Visual Basic, Managed C++, JScript, Eiffel, Component Pascal, APL, Cobol, Perl, Python, Scheme, Smalltalk, Standard ML, Haskell, Mercury and Oberon etc. The difference in performance between languages, within the framework, is very small, since they all use the same run-time representation. However, C# is designed to be a reflection of the underlying framework and can therefore easily benefit from the strengths in it. When using .NET, code needs to be CLS compliant and therefore some language constructs in some languages cannot be used, C# do not suffer from this problem. What is allowed in C# will be accepted by the framework, unless the developer explicitly states that he wants to use unsafe code.

Living with Microsoft There is one aspect not mentioned yet and we did not notice this until we searched the .NET Class Library: Microsoft tends to find it difficult to accept traditions they have not created. Even though usable patterns and constructs exist, they want to modify them a bit or rename them. This is sometimes very irritating when searching for, or dealing with design patterns. However, they have understood how important it is to provide patterns and have adapted fairly well to it. Sometimes patterns have also been improved in some aspects, as the case is with Observer and delegates. Finally, while searching the web, we noticed that there are many different opinions on the .NET phenomena. One thing is however for sure: C# and .NET should not only be debated they are definitely worth exploring.

Page 22: C# and dotNetw3.ualg.pt/~rmarcel/Csharp_and_dotNet.pdf · csg99004@student.mdh.se dsn00001@student.mdh.se sbe00001@student.mdh.se Abstract The .NET framework is Microsoft’s attempt

Copyright © 2003, Christoffer Sjöberg, Daniel Sanfridsson, Stefan Bygde

References Cited [1] “What is C#?”, DCube Software Technologies, http://www.funducode.com/csharp/basics/basics1.htm [2] “C# and Java: Comparing Programming Languages”, Kirk Radeck, http://msdn.microsoft.com/library/en-us/dncenet/html/c_n_java.asp [3] “Growing a Language”, Guy Steele, http://java.sun.com/features/2003/05/steele_qa.html [4] “Using New Cast Operators for Safe Typecasting”, Danny Kalev, http://gethelp.devx.com/techtips/cpp_pro/10min/2001/july/10min0701-3.asp Reference [5] “Automatic Memory Management”, http://msdn.microsoft.com/library/en-us/cpguide/html/cpconautomaticmemorymanagement.asp Books ”C# by Dissection”, Ira Pohl, Addison Wesley 2003 ”Börja med C#”, Karli Watsson, Wrox Press, 2001-2002 ”Microsoft Visual C#.NET steg för steg”, Sharp, Jagger, Pagina, 2002 “C#”, Darrel Ince, McGraw-Hill “Programming with C#.NET”, Ted Coombs, Thomson Learning Articles “C# and Java: Comparing Programming Languages”, http://msdn.microsoft.com/library/en-us/dncenet/html/c_n_java.asp “An Introduction to Delegates”, http://msdn.microsoft.com/msdnmag/issues/01/04/net/toc.asp “Delegates, Part 2”, http://msdn.microsoft.com/msdnmag/issues/01/06/net/toc.asp ”Programming for the New Platform”, http://msdn.microsoft.com/msdnmag/issues/1000/dotnet/default.aspx ”Objects and Values, Part I”, http://msdn.microsoft.com/msdnmag/issues/02/06/instincts/default.aspx ”Type Fundamentals”, http://msdn.microsoft.com/msdnmag/issues/1200/dotnet/ ”Boxing and unboxing in C#”, http://www.codeproject.com/csharp/boxing.asp ”Pointers undocumented”, http://www.codeproject.com/dotnet/pointers.asp ”Casting Basics - Use C++ casts in your VC++.NET programs”, http://www.codeproject.com/managedcpp/castingbasics.asp ”Using New Cast Operators for Safe Typecasting (cont'd)”, http://gethelp.devx.com/techtips/cpp_pro/10min/2001/july/10min0701-3.asp ”Comparing C# and Java”, http://www.ondotnet.com/pub/a/dotnet/2001/06/07/csharp_java.html?page=1 ”An Analysis of .NET”, http://java.sun.com/features/2000/11/dot-net.html ”.NET Platform vs Sun Java VM”, http://www.mastercsharp.com/article.aspx?ArticleID=21&&TopicID=10 ”.NET Framework Frequently Asked Questions”, http://www.andymcm.com/dotnetfaq.htm ”C# Frequently Asked Questions for C++ programmers”, http://www.andymcm.com/csharpfaq.htm ”Using Metadata”, http://martinfowler.com/ieeeSoftware/metadata.pdf ”How .NET’s Custom Attributes Affect Design”, http://martinfowler.com/ieeeSoftware/netAttributes.pdf ”So long, and thanks for all the bytecodes”, http://www.microsoft.com/mind/0998/java9110998.asp ”What You Need to Know to Move from C++ to C#”, http://msdn.microsoft.com/msdnmag/issues/01/07/ctocsharp/default.aspx “.NET Assemblies & Manifests”, http://www.dotnetextreme.com/articles/assemblies.asp “C++ -> C#: What You Need to Know to Move from C++ to C#”, http://msdn.microsoft.com/msdnmag/issues/01/07/ctocsharp/default.aspx “Operator Overloading In C#”, http://www.csharphelp.com/archives/archive135.html “Working with Namespaces in C#”, http://www.c-sharpcorner.com/Language/WorkingWithNamespacesInCSRVS.asp “Comparing C# and Java”, http://www.ondotnet.com/lpt/a/889 “Exploring the Observer Design Pattern”, http://msdn.microsoft.com/library/en-us/dnbda/html/observerpattern.asp ”Exception Management in .NET”, http://msdn.microsoft.com/library/en-us/dnbda/html/exceptdotnet.asp “Exploring the Factory Design Pattern”, http://msdn.microsoft.com/library/en-us/dnbda/html/factopattern.asp ”Top 10 Reasons for Developers to Use the .NET Framework 1.1”, http://msdn.microsoft.com/netframework/productinfo/topten/ ”Writing C# Custom Events”, http://www.ondotnet.com/pub/a/dotnet/2002/04/15/events.html “C# Tutorial, Lesson 14”, http://www.softsteel.co.uk/tutorials/cSharp/lesson14.html “C++ classes Vs. C# classes”, http://www.devarticles.com/art/1/54/4 ”Microsoft Windows Forms QuickStarts Tutorial”, http://samples.gotdotnet.com/quickstart/winforms/doc/WinFormsGettingStarted.aspx ”A comparison of Microsoft's C# programming language to Sun Microsystems’ Java programming language”, http://www.25hoursaday.com/CsharpVsJava.html “.NET: A Strategy, Not a Product”, http://www.win2000mag.com/Articles/Index.cfm?ArticleID=16127&pg=1&show=505 “Welcome to the .NET Channel“, http://www.win2000mag.com/Articles/Index.cfm?ArticleID=16079 “What is C#?“, http://www.funducode.com/csharp/basics/basics1.htm “Programming for the New Platform“, http://msdn.microsoft.com/msdnmag/issues/1000/dotnet/default.aspx Printed Article ”Nybörjarens guide till .NET”, Andreas Karlsson , DatorMagazin 11-2002 Reference sites “Visual C# Language”, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cscon/html/vcoriCStartPage.asp “Inside the .NET Framework”, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconinsidenetframework.asp “.NET Reference“, http://msdn.microsoft.com/library/en-us/netstart/html/cpframeworkref_start.asp ”Product Overview for .NET framework 1.1”, http://msdn.microsoft.com/netframework/productinfo/overview/default.asp “Microsoft .NET glossary”, http://www.microsoft.com/net/basics/glossary.asp “What is the Microsoft .NET framework?”, http://www.microsoft.com/net/basics/framework.asp “Common Type System”, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconthecommontypesystem.asp