Introducing C#


C#'s Philosophy

C# is a modern, general-purpose, and powerful language which applies two theories:

  • Object orientation
  • Type safety

C# is an object-oriented language which exploits benefits from classic object-oriented paradigm while eliminating its limitations to shape modern, powerful object orientation model. In particular, C# supports following features:

  • Modeling and abstraction
  • Encapsulation
  • Composition and inheritance
  • Polymorphism and generic type

C# allows programmers modeling programming objects from real-life objects by enabling them to create types. Each type contains only state and behaviors that are expected for application business. A type's state and behaviors are known as members of that type. Having type declarations, you could write business logic by initializing type's instances or objects and let them communicate with each other or in some cases you could even let types themselves interact directly.

While creating a type in C# you could specify which members are available outside that type and which members are not. You do so by applying modifiers on members and types. In addition, you also use modifiers to adjust other implementation aspects such as indicating a member is available at type-level or object-level. All this process is known as encapsulation.

Like real-life objects, programming objects usually depend on other objects. There are two relationships between objects in C#. An object can contain another one such as a Customer object can include contact information that is an object of Contact type. This relationship is known as composition. An object also could be derived from another one, for example an Apple object is derived from Fruit object. This relationship is known as inheritance. Both relationships make our programs more meaningful and easier to implement. A note is that unlike real-life objects or older OO programming languages, C# supports only single inheritance and eliminates multiple inheritances. This because multiple inheritances are not meaningful in most cases and using them adds more overheads on type resolving process.

Base on single inheritance, you could write certain code that work on base type and let runtime engine determines what particular derived type you intended to use in current context when the application runs. This feature is called polymorphism and is the most powerful feature of object-oriented programming. The goal to which polymorphism targets, is to help programmers to create generic code that make their programs more compact and effective. In addition, C# adds a further step in creating generic code when it introduces a so-called generic type feature. Generic type or generic for short is a way to create parameterized types so that they can be used to create concrete types for your needs. You will see generic is used very popular in generic collections and in some cases else.

So far, we know that C# is all about types creating and therefore, using types in a right way is an important issue. In earlier OO languages such as C++ you could write code like following but don't get errors until the application executes.

Customer customer = new Customer();
customer.Order();
Product product = customer;
product.Order();

C# eliminates this class of errors by enforcing a mechanism called type safety. In particular, C# requires programmers follow rules when working on types. For example, they must explicitly declare a particular type of a variable or they can not assign between incompatible variables or they can call only a type's members on an object of that type. Since this, C# is also called static typed language or strongly typed language. Not only does C# provide strict rules, but also it executes type checking at compile-time and run-time to ensure no violations happen. With type safety, C# reduces a large of subtle errors, improves programmer's productiveness, and makes program more robustness, reliability and readability.

C# and .NET Framework

C# is not created as a stand-alone language. Instead, it is a language used within the .NET Framework which is a next generation platform for writing modern applications.

By using .NET Framework, you get some important benefits as follows:

  • Support object orientation model
  • Support cross-language and cross-platform.
  • Support runtime services such as automatically memory management, code security, threading, exception handling.
  • Support types allowing developers to create any type of applications including Windows applications, Web applications, Web services, Smart device applications, and Cloud applications on Windows Azure.

To provide functionalities listed above, .NET Framework is composed from 3 components:

  • A runtime execution engine is called Common Language Runtime (CLR)
  • A vast of libraries is called Framework Class Library (FCL)
  • A set of tools including Visual Studio, compilers, utilities, etc.

In fact, .NET Framework is a Microsoft's implementation of ECMA 335 standard. This standard specifies a runtime infrastructure (commonly known as Common Language Infrastructure – CLI) required to execute so-called managed code, to allow different libraries and languages to work together seamlessly.

CLI defines an execution engine or virtual machine called Virtual Execution System (VES) as its heart. VES knows nothing but how to manage, load and execute managed code. CLI requires any language want to be used with VES must have a compiler that can compile source code to managed code.

The format of managed code has to comply with the standard CLI defines that is called Common Intermediate Language (CIL). In addition, managed code has to packed in packages called assemblies along with metadata is used to describe information about code and assemblies as well. The CLI also outlines the file format of assemblies to ensure cross-platform compatibility.

To ensure cross-language interoperability, CLI defines a unified types system called Common Type System (CTS). CTS includes common data types that are shared among languages use it. In addition, all common types must derive from a mother type that is, for example, System.Object in .NET Framework

The CTS is a necessary but not enough part to ensure code written by different languages can work together seamlessly. Because different languages have different implementation details, it is possible to have a piece of code that is valid in a language but invalid in another. For example, C# is a case-sensitive language while VB.NET is not. Therefore, if you have a piece of code with two variables have same name but different cases then that code can work in C# but cannot run in VB.NET. The result of that is VB.NET developer cannot use your code in his program.

To absolutely ensure cross-language feature can be used, CLI defines another part called Common Language Specification (CLS). It is a set of rules on which all languages must follow to create types marked CLS-compliant that means all languages will be able to interact with those types. Obviously, one of rules will be "create only types which are compatible with CTS" and another one will be "Do not create two or more variables that its names are different by only cases".

C#'s Evolution

From that time it was born, C# immediately became a preferred choice of many .NET developers due to its power and easiness. However, it is not entirely perfect language at that time and this is still true today. Realizing that and over many years, the C# design team at Microsoft have continually improved it by adding more advanced features.

The following is a briefly description about changes from C# 2.0 to C# 4.

Changes in C# 2.0

GenericA way to create parameterized types

Iterator

A way to make it easier to support foreach iteration in a class or struct without having to implement the entire IEnumerable interface

Partial class

A way to define a class in multiple files

Nullable type

A way to allow a value type can contain null value. It is useful when working with database's data types

Anonymous method

A way to create inline methods at anywhere a delegate is expected. It eliminates the need to define a new method.

Static class

A safe and convenient way to create a class containing only static members that cannot be instantiated.

Friend assembly

A mechanism to access an internal type or internal member in an assembly


Changes in C# 3.0

Lambda expression A replacement of anonymous method. It is inspired from functional programming discipline. It is especially useful in LINQ

Extension method

A mechanism allows an existing type to be extended with new methods, without altering the definition of the original type. It is also used to make LINQ available

Implicit typing

A way to declare variables with var keyword. It is used very popular in LINQ

Anonymous type

A way to create inline object to store a set of values. It is used primarily with LINQ

Automatic properties

A way to make properties with no additional logic is required

Object and collection initializer

A way to initialize objects or collections at creation time without having to explicitly invoke a constructor.

Partial method

A way to create a signature and an implementation of a method in a partial class


Changes in C# 4.0

Dynamic type A way to allow late binding to a type and therefore bypass type checking at compile-time. It is inspired from dynamic typed languages. It is useful in some special cases such as when working with COM API, with IronPython, or with HTML DOM

Named and optional argument

Named arguments enable you to specify an argument by parameter name rather than by the parameter's position in the parameter list. Optional arguments enable you to omit arguments for some parameters.

Covariance and contravariance

A way to enable implicit reference conversion of generic type parameters for interface and delegate types. It helps writing generic code more naturally and allows safe type enforcement