C#
C#
Overview
[pic]
Objectives
This module introduces the C# language. C# is a new general-purpose component-oriented language specifically designed for the Microsoft® .NET Framework common language runtime.
Although it is new to most developers, C# is not immature. Microsoft has implemented most of the .NET Framework itself in C#, putting it to the test in many millions of lines of production-quality code.
What You Will Learn
• Overview of component-oriented Systems
• Introduction to the C# language and its features
Related Topics Covered in This Lesson
• How C# eliminates common problems experienced with other languages
• How C# allows you to fully utilize the power of .NET
Recommended Reading
• Wille, Christoph. Presenting C#. Indianapolis, IN: Sams, 2000.
• Gunnerson, Eric. A Programmer’s Introduction to C#. Berkeley, CA: APress, 2000.
Section 1: C# Overview
[pic]
Section 1: C# Overview
Component-Oriented Systems
In this section we explore today’s component-oriented systems, especially COM+, and find out why and how Microsoft decided to take on a new path for component systems.
Component Concepts in .NET
Microsoft .NET, the new component platform, builds on the COM+ core ideas and introduces new thinking about component systems combined with lessons learned from COM+ and other object-oriented and component-oriented systems.
Why C#?
Lessons have been learned not only from the component model but also from how components have been implemented. Only C and C++ allow implementing the full scale of COM features, but they are not nearly as easy and productive as Microsoft Visual Basic®.
C# combines the power of C with the ease of VB and provides the most natural access to the power of .NET.
Section 1: C# Overview
[pic]
Component-Oriented Systems
COM
The Microsoft Component Object Model (COM) was introduced as the foundation of the second-generation object linking and embedding (OLE) technology that revolutionized document integration and interchange in the 1990’ has become the most successful and the most viable commercial component model in history.
COM, sometimes referred to as ActiveX®, enables document integration through OLE. More importantly, COM allows the sharing and reuse of business and user interface components across organizations and making them accessible in networked environments.
Since the introduction of Microsoft Transaction Server (MTS) in 1997, whose principles have been adopted throughout the IT industry into virtually every object-transaction and brokerage system, COM and its successor COM+ have also become the leading and most scalable platform for multi-tier, Internet-enabled systems.
However: COM shows its age
COM’s heritage, which it shares with technologies from other vendors and organizations such as Java or CORBA, is that it was developed in a time when the rise of the Internet to become the universal data exchange couldn’t be predicted.
Thus, COM and its related technologies have been designed to rely on highly available local area networks (LAN), synchronicity, and ample bandwidth. Even while some of these issues have been addressed with additions and changes to the original specifications, such changes can only be compromises and minor incremental advances because of ever-growing backward- compatibility issues.
DCOM, the network protocol of COM, is connection oriented and requires that a periodic “ping” cross the network frequently to coordinate object lifetimes across machines. Both characteristics work well in LAN environments, but introduce problems on the Internet.
Another issue that has grown with the rise of the “networked economy” and server-based computing is deployment and maintenance. Because components are shared, their registration and management is more difficult and must be done with even more care on servers than on desktop machines.
As an ironic twist, the success of COM and its vast adoption led to the increasing problem of “DLL Hell.” DLLs with the same name from different vendors, or multiple and sometimes incompatible versions of the same component, must coexist on a single machine.
Finally, and even after almost a decade of continued optimisation of tools, COM remains difficult to implement for many developers.
However: Not truly language agnostic
While COM is independent of the implementation language, with a vast array of development tools available with built-in COM support, it does make some assumptions about the binary layout of classes, interfaces, and data types.
While many languages can either be successfully modified or outfitted with powerful libraries to implement COM, there clearly are first-class (C++) and second-class languages in the world of COM.
This also applies to the type system, where sophisticated interaction between different COM-enabled languages is often restricted because their support for constructed, complex data types is not always adequate.
Section 1: C# Overview
[pic]
.NET Component Concepts
Take the best of COM+
Being aware of many of those issues, Microsoft’s architects have revisited the great, proven ideas behind COM and COM+ to build the new .NET platform:
Interfaces serve as semantically grouped contracts between parties.
Components implement one or more of those interfaces.
Programs can dynamically explore capabilities of components and find out which interfaces components implement.
Allow declarative behaviour of components by marking them transaction-aware or available for object pooling through attributes.
Add features
.NET combines component development with “true” object orientation employing inheritance.
Events are now built into the heart of the component model.
The cross-language type system and runtime as well as the unified class library make every programming language a first class citizen in the .NET world.
The .NET Framework and runtime are built on industry standards like XML and are extensible at every level.
Section 1: C# Overview
[pic]
Why C#?
First component-oriented language
As described, the .NET Framework and runtime solve and implement many lessons learned from the COM+ experience. However, many issues including component versioning and declarative behaviour through attributes do require direct support by the programming language.
While for .NET, the language C++ has been enhanced to become Managed C++, adding all of the required features, the language did certainly not become simpler.
And even with the enhancements that have been introduced to Visual Basic for .NET, many developers certainly prefer the structure of the C-language family to Visual Basic.
As a result from this, Microsoft has created C#, a member of the C-language family and the first programming language that has been explicitly designed for component development.
Power of C with the ease of VB
C# employs the brevity of the C syntax to the point of being partially source-code compatible for upgrading existing code, while being consistent, straightforward and easy to understand, a claim that cannot necessarily be made for C++.
Minimal learning curve for everybody
C and C++ developers as well as those coming from other similar languages such as Java or Microsoft JScript® will feel “right at home” in C#.
Much cleaner than C++
After a short while, C++ developers will appreciate not having to maintain separate header and source files and will certainly not miss C++ oddities such as double-colon operators.
More structured than Visual Basic
C# is better structured than Visual Basic, which is still a perfect tool for its simplicity to build ad-hoc solutions though rapid application development (RAD). For large projects, C# provides the proven C ability to express complexity in a brief, powerful and yet readable form.
More powerful than Java
Unlike Java, C# allow developers to reach out to existing C codebases through its support for native pointers in code marked “unsafe” and to directly interface with APIs and systems not written in the Java language. Through the Microsoft .NET platform, C# code always executes natively on the underlying machine, yielding maximum performance.
In addition, C# features properties, delegates and native event support, a built-in model for collections and versions, all of which are essential for component-based development.
Section 2: Elements of C#
[pic]
Section 2: Elements of C#
This section will present the elements of C#
Shape and Structure
First we will discuss the outer form of C# compilation units (files) in comparison to C and C++.
Understanding the C# Type System
Then we will explore the type system that is available to C# developers.
Understanding the C# Language
Finally we will learn the various language features and keywords that make up the language C#.
Section 2: Elements of C#
[pic]
Shape and Structure
No header files
Unlike C and C++, C# does not use or support header files.
C# employs “definition at declaration” model
C# compilation units (files) contain all declarations and definitions needed to implement a class or related classes.
This is much like the model found in Visual Basic, Pascal, Modula or Java.
C# applications are always compiled “at once” with all source files being processed conceptually at the same time. This enables the compiler to resolve any cross and forward references automatically and takes away this burden from the developer.
Similar to C++ “inline” implementation
Therefore, C# classes (with common suffix being .CS) resemble C++ classes with all methods being implemented inline.
C# does neither allow nor support declaration of methods separate from their definition.
Unlike C++, however, this style of coding does not have any implication on how code is generated.
All code and declaration in one place
Because there’s only one location to maintain, keeping declaration and definition together ultimately results in more manageable and more consistent code.
The resulting consistency also yields more readable code that is more easily understood by team members.
Finally and to access declaration only, metadata repositories in assemblies and tools that make such metadata searchable are much better for collaborative development than headers files.
Metadata also easily translates into other development languages.
Conditional compilation but no macros
A consequence (and blessing) from not requiring or supporting header files in C# is the lack of macros.
C# does support conditional compilation using the well-known preprocessor-directives #ifdef, #endif, and so on. However, macros and replacement of code elements by a preprocessor is not supported.
This may come as a shock to many C and C++ veterans but again actually helps the goal of keeping code easy to grasp and better to maintain.
Section 2: Elements of C#
[pic]
Type System
Builds on .NET common type system
The C# type system builds immediately on the common type system of the .NET platform.
Most native access to .NET type system
Since C# was designed specifically for the .NET platform, the language provides the most native access to the .NET type system features.
While this is not to say that all or any of the other .NET languages provide a lesser degree of support for the .NET type system, most of them had to be slightly modified from their core specification to match the .NET platform’s requirements.
Core Concepts
In a nutshell, the core concepts of the .NET and C# type system are:
Everything is an object in that all types in the .NET Framework, and thus in C#, are implicitly or explicitly derived from the fundamental type object.
This means that even simple, scalar types such as int can be type cast to and from the object type, be used with any container that can hold objects.
Consequently and because literal expressions are instances of a specific scalar type, the objectlike features of the type, such as supporting the ToString method, can be called immediately on the expression:
Console.Write( 256.ToString() );
However, unlike other languages whose type system is based on a shared fundamental object type, C# has a clear distinction between value and reference types.
All simple types, with the exception of the fundamental string type, as well as structures and enumerations are value types. This means that instances of these types are always allocated on the stack and when used as arguments to methods calls, these types are always promoted to the called method by value.
This eliminates the burden of dynamically allocating memory for instances of simple types and keeping track of their references, making them very lightweight and efficient.
In contrast, classes, arrays, and, of course, interfaces (which can only be implemented on classes) are reference types.
Instances of reference types are always dynamically allocated and their use is tracked by the runtime for garbage collection (more on that later).
When used as arguments to methods or being assigned to fields or variables of their type, these types are passed using a reference to the once allocated object.
The distinction between value and reference types reflects their purpose:
Value types are the most essential building blocks used for writing any logic or functionality and must therefore be lightweight and extremely efficient.
Reference types do contain the implemented logic and its data or hold references to such types, making them “heavyweights” by nature.
Section 2: Elements of C#
[pic]
Simple Types
Integer Types
C# supports signed and unsigned variants of integer number types ranging from 8 to 64 bits.
The byte and sbyte (signed byte) types are 8 bits wide. The short and ushort (unsigned short) types hold 16 bits, and the int and uint types hold 32 bits.
Unlike C/C++, the long and ulong types in C# are always 64 bits wide, providing an ample value range for almost any usage scenario.
Also different from C++ is that the signed and unsigned types are really types in their own right and not just treated as a variant of the base type int as in the C++ declaration
unsigned long int a;
To clarify intent and eliminate the confusion caused by them in C/C++, the C# language does not support the length and sign modifiers signed, unsigned, long and short, but the developer must explicitly use one of the mentioned types.
IEEE Floating Point Types
Just like C and C++, C# supports the float and double data types as defined by the IEEE 754 standard.
The float type is internally represented by 32 bits and has a precision of 7 digits with a value range of approximately 1.5 × 10−45 to 3.4 × 1038.
The double type is 64 bits wide allowing for a precision of 15 to 16 digits with a value range of approximately 5.0 × 10−324 to 1.7 × 10308.
Although these types are common to every programming language nowadays, it should still be noted that they are not exact numeric types and only reflect a value “as close as possible” to the intended result of a calculation and thus may not be the best choice for financial calculations.
However, because they are directly supported by most underlying hardware, floating-point operations using the IEEE types yield excellent performance.
Exact Numeric Type
For calculations that require exact numeric calculations, such as in finance, C# features the native decimal type.
Values of type decimal are internally represented by 128 bits, providing a value range from 1.0 × 10−28 to approximately 7.9 × 1028. More precisely, the type is a 96-bit integer scaled by a power of ten represented by the remaining bits.
The precision of the decimal type is 28-29 digits with a maximum of 28 decimal places.
Character Types
The char type represents a single character. It is worth noting that unlike C/C++, the char data type is not equivalent to any of the integer types and should really only be used to hold character data.
Even more so, char is equivalent to a single byte, but is 16-bit wide and always holds Unicode characters.
Sequences of characters form strings. And because strings play such an important role in applications, C# has native support for strings through the string data type.
There are several noteworthy characteristics of the string type that differ from all other simple types:
Unlike all other simple types, strings are managed as by-reference types since they may have indefinite length and are therefore “heavyweights.” The string type is actually an alias for the .NET Framework’s System.String type, exposing all the capabilities and methods.
This includes rich support for operators, such as string concatenation using the plus (+) operator and relational operators.
Boolean Type
The bool type represents the two states true or false.
All flow-control statements (we will learn them a bit later) that direct the flow of control through conditional expressions require the use of the bool data type.
The bool type is not interchangeable with any of the integer data types.
Section 2: Elements of C#
[pic]
Enums
Named elements used instead of numbering options
Enumerations are very common in many programming languages including C and C++, but used rather rarely in the latter two. Instead, many developers still prefer using constants or #define expressions in these languages.
C# intentionally does not support global (unscoped) constants or preprocessor macros and definitions except for conditional compilation. For selector values that describe options for functional behaviour, enumerations shall be seen as a full replacement to both constructs.
Strongly typed
Enumerations are always strongly typed and are not interchangeable with integer number types.
Better to use “Color.Blue” than number expression
Using enumerations for method arguments or as property types enforces readability for C# code. In the given example, the expression Color.Blue is more readable than a numeric selector with the value “2” (taken from the example on the slide). Enumerators assign clear semantics to a selector, while a plain numeric expression can be anything.
Still, enumerators have the same advantages as integer types in that they are value types and therefore very lightweight.
Section 2: Elements of C#
[pic]
Arrays
Zero based, Type bound
Arrays in C# are strongly typed and zero based. For developers not accustomed with the C language family, this means that the first element of each dimension in the array can be found at the index-position 0 with the upper index being at n-1 if the array capacity is n.
Built on .NET System.Array class
All arrays declared in C# are based on the .NET Framework’s System.Array class and thus have all of its capabilities.
This includes being enumerable with the foreach statement that we will explore a bit later, as well as being sortable and searchable.
Declared with type and shape, but no bounds
Because arrays in C# are objects and reference types, they do not require their bounds to be specified at declaration time.
This overcomes the common problem of not exactly knowing what bounds an array should have under certain circumstances. To solve this, most developers play safe and over-allocate the array-bounds to suit their needs. While C++ knows this type of declaration for a single dimension of an array, its usage is not consistent throughout the language.
In C#, arrays are always declared specifying their shape only. The shape determines whether the array is a list (like int[]), a matrix (like int[,]), a cube (like int[,,]), or some hyper-dimensional space. Another shape is jagged arrays, which are declared with consecutive square bracket pairs and represent “arrays of arrays.”
Created using new with bounds or initializers
To create an array, you must use the new keyword along with an array expression that specifies the bounds for the array to be created.
Obviously, the array to be created must be compatible with the declaration in terms of shape and number of dimensions.
Once created, arrays are static in size and cannot be re-shaped, shrunk, or grown.
Section 2: Elements of C#
[pic]
Namespaces
Every definition must be contained in a namespace
The most important structural element of C# are namespaces.
Every definition of a C# application must be contained in a namespace that, in turn, may be contained in another namespace.
Because of this strict rule, all C# code is forced into a hierarchy of namespaces and thereby into a certain order, which makes projects easier to structure, navigate, and understand.
To underline namespace’s importance: they are the only means by which a C# compilation unit (source file) can reference and import other code, with the using keyword. To further enforce this model, C# does also not recognize file-based inclusions like C’s #include statement.
Can and should be nested
Namespaces can be nested, and this feature should be used intensively by projects to define their structure.
A possible naming convention for your projects may be “...,” but you are actually entirely free in how you structure your namespaces.
Group classes and types by semantics
When a namespace structure is adopted from this model, any namespace name implies certain semantics for the classes and types contained in the namespace.
If the namespace name reads “AcmeCorp.ERP. BuyerSystem.DataAccess” you too would expect that namespace to contain classes that deal with just what the name says: data access.
Using nested namespaces makes code more readable and easier to comprehend.
Section 2: Elements of C#
[pic]
Interfaces
Declarations of semantic contracts between parties
Interfaces are one of the core concepts of component-oriented development and the prime reason for the success of the COM+ development model, which we are all accustomed to.
For .NET, interfaces play the same central role as they have been playing for COM, defining a clear semantic and technical contract between parties co-developing component-based systems.
Define structure and semantics for specific purposes
An interface declaration describes two things at once:
• A structural, technical contract containing properties and method signatures that can be implemented by one or more server components and be consumed by one or more client components.
• A semantic context that assigns every method and property a narrowly defined function and meaning.
For component systems to work, both aspects are of equal importance.
If you implement an interface named ICustomer that has been defined to expose methods and properties for a customer and that interface would also fit your needs to implement a supplier component and you actually do so—you are breaking a contract.
Consumers of your component will rely on ICustomer representing a customer since the documentation for ICustomer (that you may not have written) tells them so.
Abstract definitions of properties and methods
Interfaces are purely abstract classes that contain no implementation.
“No implementation” means that they cannot contain any fields or code, but they can contain events, properties, and abstract method declarations.
Support (multiple) inheritance
Interfaces may inherit their properties and methods from other interfaces.
Multiply inheriting interfaces into an interface or into a class makes the statement: ”This new interface K is a specialization of what is represented by interface A having the additional capabilities B and C.”
What you do with multiple-inheritance at this point is to assemble certain distinct capabilities that an implementing class should have into a single interface forcing an implementing component to provide the full contract.
We will get back to this discussion once we have learned what classes are.
Section 2: Elements of C#
[pic]
Classes
Implementation of code and data
Classes are the core concept for object-oriented applications. A class groups data and all code that handles this data into a tightly coupled unit.
Implement Interfaces
A class implements interfaces that have either been defined as distinct interfaces as we have learned on the previous slide and always the interface that the class itself defines through its own signature.
In C#, every class may implement as many interfaces as necessary, allowing to expose multiple, well defined capability sets from a single component.
Allows to inherit single base class
At the same time, classes may only inherit implementation from a single base class.
This is different from C++, where implementation can be inherited from an arbitrary number of base classes. However, multiple-inheritance in C++ is often a source of great confusion, which is difficult to understand and maintain and ultimately too rarely used in real-life applications to justify the complexity.
C# classes may only inherit implementation from a single base class. Additional capabilities can be implemented using additional interfaces.
Classes’ Elements
C# classes may contain the following elements:
• Field is the C# term for member variables, or “instance variables” as they are sometimes also called. A field is specified with its type and a name and the desired access protection level. In C#, fields may be assigned a default value at declaration time using an expression such as public int myvalue = 7;
• A property (we explore them more in detail a bit later) is a named value that acts and feels like a field for consumers of the class, but it is implemented using a pair of get and set methods.
• Methods are functions that implement the logic of the class and contain its code.
• Further possible class elements are delegates, events, and indexers; we will learn about these in detail later.
Section 2: Elements of C#
[pic]
Structs
Group of data and code
Like classes, structures implement semantically motivated groups of data and code.
Similar to classes, but with important differences
However, unlike classes, structures may not inherit other structures or interfaces and thus have no “objectness” to them.
The reason for this is that structures are by-value types and serve to provide a container for very lightweight, small groups of data that come along with some handling code.
Good examples for this are points representing coordinates in a graphics system. In such a system, points have to be managed and kept in great numbers. Keeping every single point as a reference type that needs to be individually tracked by the system for memory management and maintaining identity would dramatically reduce the system’s overall performance.
Classes vs. Structs
The role differences between classes and structs are therefore:
• Structures are lightweight data containers for small data-items that appear in great numbers and for which identity does not need to be maintained
• Classes are used for rich objects with their own identity (by reference) that need to be handled by consumers and containers.
For C++ developers it should be explicitly noted that class and struct are indeed vastly different in their semantics and do not have the same relationship as they have in C++. In C++, a struct is essentially equivalent to a class with the difference that structures do not provide access protection. This is not true for C#.
Section 2: Elements of C#
[pic]
Properties
Mix between fields and methods
Properties in C# are a mix between fields and methods. For any consumer (or client) or the class’ instances, properties look and feel much like fields in that they can be accessed in very much the same way.
You assign values to them and can retrieve values for them by just specifying their name in an expression.
Inside the class, though, properties are implemented using a pair of get and set methods.
The get method must return a value of the property’s type, while the set method has an implicit parameter value through which it receives the value the caller wishes to assign to the property.
Inside both methods, the code may be written in any shape or fashion.
If you wish to make a property read-only, just omit the set method. If, for any reason, you want to provide write-only properties, omit the get method.
Property usage scenarios
Properties have a wide range of uses, although that may not be immediately obvious to developers coming from languages like C++.
For client developers, properties are easy to access, look like variables and are a very natural way to access a class’ data.
At the same time, it is best practice in C++ to make all members protected or private to ban external, direct access to members, because such action may have adverse effects on the operations of the class as the client may have no insight in what the class is actually doing with that data.
Properties are used whenever you want to provide access to members, but in a controlled fashion.
In the set method you can perform validation of the incoming value and reject it or alter it as necessary.
In the get method you can compose a virtual value from your object’s state that you are composing on the fly. Example: You may have an address class that has all of the address parts like city, street and so on. The class may then also have a property FormattedAddress that composes a nicely formatted address block in its get method and may even be able to parse out the parts from such a block in its set method.
Another important aspect is that properties can be declared also on interfaces, allowing for a richer and more intuitive contract than you could define with only methods.
Section 2: Elements of C#
[pic]
Indexers
Consistent way to build containers
Indexers are the way to build indexed containers in C#. In fact, C#’s own arrays and all other collections that allow “square-brackets” access use indexers to enable access to their content.
Because of indexers, your own containers are in no way different from the language’s built-in containers, making C# programs more consistent and easier to comprehend.
Build on properties idea
Indexers build on the properties idea that we have already explored. An indexer is implemented using a pair of get and set methods.
The syntactic difference is in how they are declared. Since multiple indexers with different semantic meanings do not make sense for accessing a container, the indexer is declared using the this keyword with square brackets declaring the index argument.
Allow indexed access to contained objects
Using indexers, you can create collections or any other type of class than requires some type of indexed access to contained objects.
Index qualifier may be of any type
It is also important to note that the index qualifier may be of any type; thus, you are not restricted to integers or strings, but may also use classes or structures to refer to the data.
Section 2: Elements of C#
[pic]
Delegates
Similar to function pointers found in C and C++
Delegates are the C# version of what languages like C and C++ call function pointers.
The concept behind the name is that delegates are placeholders for methods, which delegate the call to a distinct, previously assigned method. Delegates are the tools to use in C# to implement callbacks or, as you will learn in a minute, to implement event handlers.
Strongly typed, no type-cast confusion or errors
Delegates are strongly typed, and because they are not pointers, they do not cause the confusion and resulting bugs that C developers often experience. The Win32 API, for instance, employs only very few actually declared function pointer types through which many different callback types with vastly different signatures are handed into the Windows internals. In the C language, function pointer types are nothing more than syntax sugar that is not thoroughly verified and, hence, a frequent source of hard-to-catch bugs. Delegates are very strongly typed and cannot be type-cast or otherwise converted to a delegate with a different signature – thus eliminating this bug source.
Declaration creates typed method signature
Delegates are declared using the delegate keyword followed by a method signature whose name identifies the delegate type:
delegate void Clicked(Element e, Point p);
To declare an actual delegate, you use the defined delegate type to declare a variable that you can assign methods to:
Clicked MyClickedDelegate;
Actual delegate is instance of this type
The actual delegate that you can call is an instance of the delegate type that you create using the new operator and passing an object method that exactly matches the signature.
This assumes that you have an instance obj of a class that may look like this:
public class Form
{
public Form()
{
// initialize
}
public void OnButtonClick(Element e, Point p)
{
// handle the button click
}
}
Assigning a method to a delegate is as easy as assigning a value to a variable, avoiding the multitude of sometimes even contradictory rules found in C and C++.
MyClickedDelegate =
new Clicked(obj.OnButtonClick);
Section 2: Elements of C#
[pic]
Events
Events
With its native event support, C# embeds the event-driven development model that all developers in the Microsoft Windows® environment are familiar with into a C-family language and does so in a very extensible way.
C# events build on and use the concept of delegates. To declare an event you use the keyword event, specifying a delegate type and a name for the event.
Taking the delegate declaration from before, declaring an event is very easy:
event Clicked OnClicked;
Clients subscribe to events by adding a delegate instance that’s compatible with the event’s delegate type using the += operator. Likewise, clients unsubscribe by removing their callback from the event using the - = operator.
btnAction.OnClicked += MyClickHandler;
Inside your class, the event source, you can now simply call the event using the delegate’s signature and the name of the event, every time you want to notify all registered event sinks that the event occurred.
OnClicked(this,PointerLocation);
Section 2: Elements of C#
[pic]
Attributes
Similar to attributes known from IDL
If you have developed COM applications using Visual C++, you will be familiar with the Microsoft Interface Definition Language (MIDL). MIDL defines the contracts between applications and generates all the code necessary to communicate these contracts over networks and across process boundaries.
Besides being a C-like definition language that allows you to define structures, interfaces, functions, and class-layouts, MIDL features a very rich set of attributes that you can use to give the MIDL compiler hints about what the declaration you have just written precisely means.
For MIDL, it is vital to know whether a method argument that you have declared must be transmitted over a network in a one-way-in [in], one-way-out [out] or in a bi-directional fashion [in,out].
Now, instead of twisting and tweaking the clear and easy C-style way of how declarations are done in MIDL for every new feature in the wire-protocols, all aspects of how the information is being transferred over the network are declared using attributes. Attributes augment a definition—which is sufficient for a compiler to understand and translate—with certain semantics that are necessary for a tool using this code to function correctly or to enable special functionality by the presence of the augmentation.
In our MIDL example, the [in] attribute is not necessary to create the header files for the C++ language from MIDL and, thus, not part of the contract itself, but it is essential to generate the correct code that takes care of transmitting the data over the network.
Because the attribute model worked so well to declare behaviour and functionality for MIDL, the attribute model had then be expanded into the COM+ space by allowing to augment components with attributes that define their behaviour in transactions, their security requirements and other aspects like pooling and activation policies.
However, unlike MIDL attributes, COM+ attributes cannot be declared right in the program code, but have to be added to the components at the deployment stage.
.NET unifies those attribute models by allowing COM+ attributes and other predefined or custom attributes declaring the behaviour of elements to be specified in the programming language, making those attributes an integral part of an application’s descriptive metadata.
Declarative access to functionality
Consequently, C# allows you to augment elements like methods, properties, fields, or classes with attributes that can be evaluated by the runtime environment or custom code to provide functionality to your code without requiring you to actively write the plumbing for it.
If you want to enable transactional behaviour for a serviced component class and want to mark it as requiring a transaction, virtually all you have to do is to specify the attribute [Transaction(TransactionOption.Required)] and the runtime and COM+ services will take care of the rest for you—also eliminating deployment hassles.
Extensible through custom attributes
Unlike MIDL and COM+, C# does not restrict you to using “what’s there.” You can create your own attributes that have the same power as any of the predefined attributes.
Code augmentation
In short, attributes allow you to augment code to automatically add functionality by “declaring a wish.” They also allow you to define precise semantics for certain expressions that you may want to use to dynamically extract data from classes, regardless of whether they implement a certain interface or follow a predefined naming scheme.
Section 2: Elements of C#
[pic]
Creating Custom Attributes
Implement with the Attribute suffix
You create an attribute using the desired attribute name with the suffix Attribute appended as the name of a class that is being derived from the base class System.Attribute. The constructor(s) can receive additional arguments that can be stored inside the attribute to further specify its function.
Automatically extend language
Once you have an attribute like this defined in a namespace, you can use it—without the Attribute suffix—to augment other classes in any context using that namespace.
Explore through .NET Reflection
To explore and find whether a class or any other element carries attributes, get its type using the typeof operator or calling GetType() on an object and then retrieve a collection of attributes using the GetCustomAttributes() method.
Section 2: Elements of C#
[pic]
Statements
Up to this point, we have explored the structural elements of C# in depth. Now it is time to take a look at what makes the language tick: statements.
Very C: Flow Control and Loops
The flow-control elements of C#, such as conditional branching with if, selective branching with switch, or loops are very similar to what developers know from C or C++ and even Java.
The core differences from C are that conditions are strongly typed to always expect expressions that yield a bool type value and that C# cleans up some great source of confusion related to the C/C++ switch statement.
In C and C++, you must explicitly put a break; statement at the end of each case label’s block to have the control flow exit the switch block after processing the case. If you do not place the break; statement there, control simply “falls through” to the next block.
While some developers hail this as a programming technique, it is a traditional source of hard-to-see bugs for all the other developers, and thus C# does not allow this fall-through.
Very not C
Some statements, however, are new to the C family:
The statement lock() is a language-inherent way to synchronize access to objects in multithreaded environments, which, by default, any .NET application is. Every object in .NET (and C#) has an implicit critical section assigned to it; while the code is inside a lock-block, all other access to that resource is queued up until the blocking thread exits the protected area.
The checked and unchecked statements serve to instruct the compiler to generate code that either checks for integer overflows at compile time or run time or explicitly suppresses these checks. This is very useful in scenarios where you may multiply two integer values whose product exceeds the capacity of the value you assign the result to. Depending on your context, this may or may not be by design. C# allows you to explicitly state your intent. By default, all code in C# is “checked.”
Section 2: Elements of C#
[pic]
Collections Built-in: foreach
Straightforward support for iterating over collections
The new C# statement foreach is a simple and elegant solution for one of the most common tasks in object-oriented programming: iterating over collections.
The statement can be used with arrays and any other .NET collection using the very straightforward syntax shown on the slide.
Can also be used with any custom class
In addition to being able to use foreach with the built-in array types, you can implement your own, enumerable containers that work with the foreach statement.
Any enumerable container implements the interface IEnumerable. This interface defines a single method GetEnumerator() that returns an object implementing the IEnumerator interface.
The enumerator itself is a very simple object that just keeps track of an index into the collection to be enumerated. For navigation it provides the methods MoveNext(), which moves to the next item in the collection and returns it, and Reset(), which puts the index back to the start of the collection.
Section 2: Elements of C#
[pic]
Operators
Very C:
The logical/conditional operators for AND (&&), OR (||), and XOR (^) as well as the arithmetic and relational operators are equivalent to their C counterparts in function.
Not exactly C:
However, there are subtle differences in the way the operators ampersand (&) and pipe (|) work when used as single symbols.
When they are used with integers, they perform a bitwise AND or OR, just as in the C language.
If they are used with conditional (bool) expressions, they do evaluate the expression fully, instead of using a shortcut. This means that while an expression like “1 == 0 && isValid( a )” will never result in a call to the isValid function, because the first expression can never be true, the expression “1 == 0 & isValid( a )” will always evaluate both conditions.
Very un-C:
Unique to C# are the operators is, as and typeof.
The is operator allows you to test whether an object is an instance of a specified class or implements a certain interface.
The as operator allows you to cast an object to a specified type in a type-safe manner. Regard this as the C# version of QueryInterface.
Finally, the typeof operator allows you to retrieve a Type object that contains the full description of the runtime type and that you can use to dynamically explore attributes, methods, fields, and all other aspects of the type. Regard this as the equivalent to COM type libraries, but with the huge difference that all of this information is at hand through a simple operator.
Section 2: Elements of C#
[pic]
Operator Overloading
All arithmetic, relational, conditional, and logical operators can be overloaded
C# allows the overloading of virtually all the common operators to enable a class designer to make the class look and feel like any other arithmetic or logical object or to provide brief expressions for what would otherwise be achieved through method calls.
The simple way event sinks are added to and removed from events is a very good example of the benefits of operator overloading.
No overloading for assignment and special operators
While you are able to shape the semantics of operators to your needs for most operators, some operators have a very narrowly defined meaning in the context of C# and, thus, cannot be overloaded for any class.
This includes the special operators like sizeof, new, and is, but also the assignment operator. By default, the assignment operator of C# performs a complete, shallow copy of value types on assignment; for reference types, assignment means to pass a reference to an object. These semantics cannot and should not be altered in C#.
If you want your classes to support customized cloning (what C++ assignment operators are used for), implement the predefined ICloneable interface. If you are happy with a member-wise, one-to-one cloned copy of an object, invoke the MemberwiseClone() method that is available on every object in C#.
Section 2: Elements of C#
[pic]
Access Protection
Adopts C++ model
To specify who may or may not access a field or property or call a method, C# adopts the C++ model.
However, unlike C++, the access protection level is set explicitly per element and not using labels.
The public protection level means that everyone may access this element. The protected level means that members of this class and all derived classes may access the member.
Private is the default protection level in C# inside classes. Private means that only members of this exact class may access this element.
Expands C++ model
Based on C++ experience, C# goes beyond the C++ model and defines additional protection levels:
• sealed can be applied to classes that may not be used as a base class for any other class. While this may seem to contradict the object-oriented model, this is actually useful for certain scenarios where class library designers want to enforce a certain way of using a library and want to prevent its behaviour from being altered.
• internal is very useful for class library designers who do not want access restrictions between classes of the same library, but want to deny client code access to internally public members. In the “current” assembly (in which this code resides), internal is equivalent to public; for all other access internal is equivalent to private.
If internal is equivalent to public inside an assembly, there has to be a way to make those elements protected outside that space at the same time; protected internal is designed to achieve this.
Section 2: Elements of C#
[pic]
"Pointers, I need pointers!"
C++ developers looking at C# for the first time and not seeing their familiar pointers all over the place may be tempted to cry “Foul!” However, the design of C# eliminates most scenarios in which pointers are commonly used in C++.
C# support for references
As a starter, C# has a built-in string type with a set of methods that covers all of the functionality (and a bit more) of what the C standard run-time library provides. In C# all strings are also Unicode by default, essentially eliminating the need to transform back and forth between different character models.
C# also supports a rich and efficient collection model through .NET that is easy and intuitive to use and provides all the basic plumbing for containers that you are often forced to write yourself using C and using pointers.
Reference arguments are supported in C# with the ref keyword, and outbound arguments use the out keyword, so pointers are not required in these cases.
Pointers are available for code marked unsafe
However, C# respects that there may be some good reasons for using of pointers. Because C# is related to C, one of the reasons might be to port existing C code to C#.
Another would be dealing with actual memory locations obtained through calls to the .NET P/Invoke layer.
Section 2: Elements of C#
[pic]
Boxing and Unboxing
By-value types can be “boxed” and “unboxed”
We have learned earlier that C# makes a clear distinction between value and reference types. There are, however, instances, where you may want to use value types as reference types.
If you do, for instance, have a struct type that’s usually passed around by value, but for some methods you want to use that structure as a by-reference container, you can “box” that value by assigning it to a variable of type object. The variable will then receive a copy of the value and contain it.
To unbox the referenced copy, you simply type-cast the variable back to its native type and assign it to a variable of that type.
Boxing allows values to travel by-ref
Since the fundamental object type is a by-reference type, the contained value will subsequently be handled as a reference of type object.
Based on object-ness of all types
“Boxing” can be performed with all value types, because every type in the .NET Framework is conceptually based on the System.Object type (although C# doesn’t make that immediately visible).
Think: Throw value in a box and reference the box
The principle of boxing and unboxing to create references is really simple having this picture in mind:
Write your boss’s private cell phone number on a flip chart. Everyone may then hastily write a copy into their notebooks. That would be “by-value.”
Now, program the number into your own, old, boxy cell phone assuming there is a way to hide the “raw” number and just let the phonebook entry for “MyBoss” appear. The number is now boxed. Those who want to promote their own career must use your cell phone, because it has a shared copy of the number. If the number changes, you can modify it and everyone will still be able to call by the phonebook entry.
That would be “by reference.”
Section 2: Elements of C#
[pic]
Garbage Collection (1/2)
C/C++ applications often leak memory
The C language family and many other languages require the developer to manage memory manually. If you need a memory block to contain a string that you can return to a caller, you must allocate that block and once the caller doesn’t need that block anymore, he must discard that block explicitly. Of course, the same applies to C++ objects, which you allocate using new and free using delete.
Besides the most common source of memory leaks, which is simply to “forget” to release an allocated memory block, the main problem with manual memory management is that there are no clear rules for ownership.
Sometimes the caller of a method may be responsible for preallocating memory and freeing it once the called method returns. In another case, the called method may free the memory and in yet another case the caller may receive a reference to a dynamically allocated memory block that is still owned by the called object and, thus, must never discard it. The same confusion is true for C++ objects.
While every development organization has its own standards on how to overcome this problem, it is not clearly regulated by the C language. And when it comes to sharing code between organizations, confusion starts yet again.
COM fixes this partly through ref-counts
In COM, there are very clear rules on how to manage dynamically allocated memory and especially on how to deal with ownership of object references.
If you obtain a reference to an object you call AddRef, and you don’t need the reference anymore, you call Release. If the internal usage counter of the object drops to zero, the object discards itself.
While this helps to clear up the confusion, it doesn’t necessarily lead to fewer memory leaks, because calls to AddRef and Release must always be balanced. And at that point we are back at the “forgetting” problem.
While the balancing can be managed by smart pointers like ATL’s CComPtr class, there are still scenarios where even smart pointers may not be able to avoid leaks.
The same is true for nonpointer environments such as Visual Basic, which do use a scheme like smart pointers, but still require the developer to explicitly free objects at some places by assigning a “Nothing” value to the references.
Server applications must be leak free
The danger of memory leaks is a major problem for server applications. It would be unrealistic to expect applications written in C/C++ to be leak-free unless thorough testing is done on them in all possible usage scenarios. In reality, many larger applications will and do still leak memory at some places.
While it is often regarded a somewhat tolerable problem for desktop applications to leak a few bytes here and there, it is a major killer for server applications.
Server applications should be “configure and forget” and must be running for several months, if not years. Leaking a just a couple of bytes at a single method may stack up into the multiple-megabyte range over time, affecting performance and ultimately bringing the system to a halt.
To make things worse, such tiny leaks are nearly impossible to track in large applications.
Solution: Automatic Memory Management
The only real solution to this is automatic memory management using garbage collection. Garbage collection frees the developer from the burden of manually tracking memory use and ownership and allows the system to reclaim unused resources automatically.
Garbage collection is a mechanism to protect applications and their developers from hard-to-find bugs.
Section 2: Elements of C#
[pic]
Garbage Collection (2/2)
Developer creates new object and data arrays
In C#, all objects and data arrays are created using the new keyword. C# and the .NET Framework do not support any explicit memory allocation functions/methods.
Runtime tracks all uses automatically
For all reference objects having been allocated using new, the runtime tracks all uses and references automatically without requiring (or allowing) the developer to interact with memory management.
GC automatically removes all unused objects
Once the runtime determines that an object is no longer in use, it marks the object to be collected at the next pass of the garbage collector. The garbage collector does not run continuously, but only when a certain threshold of memory usage has been exceeded.
More efficient memory management
Freeing up memory can be a very expensive operation if memory becomes fragmented over time and thus the cost of coalescing blocks rises. Because objects are being marked for collection first and only actually collected periodically, the memory manager can roll this task into a single operation, increasing overall performance.
In addition, and due to the lack of direct memory pointers, the memory manager can rearrange memory blocks as needed to further optimise memory use.
Ease of use and “zero memory leaks”
The “fire and forget” model of garbage collected memory management is very easy to use, easy to understand, and has the very positive side effect of enabling application to claim the feature “zero memory leaks.” As stated before, this is essential for server applications.
Section 2: Elements of C#
[pic]
Nondeterministic Destruction
Garbage Collection downside
C++ developers are accustomed to having a class’s destructor called whenever an object is freed, and many design their classes to reclaim external resources like file-locks or database connections at this point.
This doesn’t work in C#. While C# features destructors, the garbage collector will call them when the object is actually freed and that may be at some indeterminable future time and may not be before the application terminates altogether.
Holding limited and expensive resources such as database connections until the destructor is called is therefore not desirable in C#. If you browse through C# samples, you will rarely or never find any destructors implemented, because garbage collection makes them mostly obsolete on the one hand and useless on the other hand.
Use IDisposable with using
Instead, you should use a design pattern that's built right into the .NET Framework. For each class that consumes external resources, you should implement the IDisposable interface with it's single method Dispose(). In the implementation of the Dispose() method, you should immediately release all external resources like files or database connections that your on your class uses.
The consumer of your class can call this method either directly or better use your class with the using keyword. If a variable expression is used with using, the method Dispose() is automatically called as soon as the scope of the using block is left.
Most classes of the .NET Framework that handle external resources, like those in or in System.IO, implement the IDisposable interface. If you hold on to an instance to one of these classes within your own class, you should make it a habit to implement IDisposable yourself and pass the call on to the instances you reference.
Section 2: Elements of C#
[pic]
Exception Handling
Very similar to C++ and SEH
Exception handling is one of the most important features of modern programming languages and system environments. It allows the developer to write applications in an optimistic way, assuming that a certain block of code will work as designed most of the time and then specify and define the handling of exceptions, that is, how the code behaves if things don’t go quite as planned.
For example, if a certain section of code wants to open a file that usually exists, exception handling will enable you to write your code as if opening the file will always work, and the exception handler will take care of the rare case when the file isn’t there.
With proper design of exceptions and exception handlers, code becomes usually a lot more legible, because its structure is not focusing on what could go wrong, but on what the code tries to achieve.
COM developers certainly know those seemingly unlimited levels of nesting SUCCEEDED and FAILED conditional expressions, which make COM code sometimes very hard to read and understand. Thus, they will appreciate that C# and the entire .NET platform now supports a consistent exception model that works across process boundaries and all languages.
C#’s exception handling expressions are very similar to the model known from C++ or the structured exception handling (SEH) of Win32®.
The entire model more closely resembles C++, though. If a method that is being called does fail, it can throw exceptions using the throw statement. An exception is simply an arbitrary object whose type is being evaluated by all catch blocks on the call stack as the exception falls down through the caller hierarchy. If there is a match for the exception’s type on a catch handler, the catch handler is invoked and can take appropriate action.
Read like this: try—catch—finally
As in C++, the keywords for exception handling are try, catch, and finally. To understand the model, try reading it like this:
First try executing the enclosed code. The code makes no assumptions about what could go wrong, but, in contrast, is designed as if no critical event could occur at all.
Of all critical events, such as the inability to access a system resource, catch those that are expected to be happening and for which handlers have been defined.
Finally, and regardless of whether an exception occurred or the code executed normally, perform a proper cleanup of this code section.
The most delicate issue in this model is the proper design of the catch handlers.
First, you can specify a “global” catch handler by just specifying the catch keyword. This handler will intercept any exception thrown by any called method. Catching exceptions this way is the easiest, but your code is expected to handle any situation from a failed precondition to security violations to a severe system problem in a single handler. This is really only appropriate for debugging and top-level, “last-resort” exception handlers.
More likely is that you want to handle exceptions in a cascaded way, handling those that you expect to occur in your try section explicitly and writing handlers for more general and severe exceptions at subsystem or application level.
You can achieve this level of detail by intercepting exceptions using the catch keyword followed by a single argument that specifies the type of exception you want to handle in the following block. The catch block will then intercept exceptions of the specified type and, because it is all object oriented, also all of its derived types.
A single try block can have an unlimited number of catch expressions followed by a single finally block.
Section 2: Elements of C#
[pic]
Core Differences from C++
C# looks a lot like C/C++
Since we have seen numerous references to the C and C++ language throughout the presentation, this would be a good point to sum up the core differences.
The language structure with its basic statements, types, and structure (code blocks, and so on) closely resembles the C and C++ languages and identifies C# as a member of the C language family.
However, even at first sight, C# code looks more “streamlined” and appears easier to read. This is due to some notational differences that we have already learned. Let us recall just a few:
• Having all code “inline” (and no header files) eliminates the C++ “double-colon” notation and makes arbitrary scattering of code over multiple files impossible.
• Access protection is defined on a per-element basis and not with labels.
• Explicit nonsupport for macros avoids hiding and replicating code that is hard to debug and analyse.
• Enforced order through namespaces.
But beyond making code more legible, the C# language design does something much more important:
Fixes a lot of common bug sources
To improve is to learn from errors, and that is what C# does. The C and C++ language have certain weaknesses that lead to very common programming errors, and the designers of C# have tried to eliminate a lot of those by design.
C++ has been a major improvement over C, with its stricter type checking at compile time, which has meanwhile been extended to also feature run-time type-checking support through RTTI. However, C++ still allows one to “reinterpret” data from one type to another type without conversion. C# does not. C# makes conversion between types mandatory and is extremely unforgiving with run-time type-cast failures, making C# the most type-safe language in the C language family.
The switch statement is one of every C and C++ beginner’s nightmares; its “fall-through” rule is nowhere near being intuitive and the break; statement is easily forgotten. Consequently, C# does not support fall-through.
Any Boolean expression is strongly typed. There are millions of errors in C and C++ code that stem from C’s int-ness of conditional expressions, which allows statements like if( a = b ) instead of the intended if( (a = b ) != 0 ) … or is the intent actually if( a == b )?
C#’s access protection is also an improvement over C++ in that it supports “internal” protection and eliminates the confusing friend keyword. More important, though, is that C#’s model actually works. Even if you do not have access to the code, C++ allows you to tamper with the header files to eliminate the intended protection or to abuse the preprocessor to #define private as public.
Very obvious is that C#’s automatic memory management and its lack of pointers for safe code makes protection faults much less likely, since developers cannot access unallocated or protected memory areas.
And by the same token, automatic memory management allows developers to get more sleep: No more hunting for memory leaks until 3:00 in the morning.
Section 2: Elements of C#
[pic]
Class Version Management
Real-Life Scenario
Being component oriented, C# is the only language in the C language family that has built-in class version management rules.
To be clear: When we are talking about versions, we talk about the incremental changes a class undergoes when code is being revised. We are not talking about labelling code with version numbers, which is, seen from the source-code level, entirely arbitrary. (Yet, this can be achieved using attributes.)
Consider the following example:
Two developers of two different organizations write two separate pieces of software. To make the example easy to understand, consider that one of the developers works at Microsoft and the other one is you.
You write a class that builds on the Microsoft developer’s class—more precisely, you derive from the Microsoft class.
In your class, you implement a method called CalcResult, which performs some calculation based on the inherited information and some information you added.
Now, you get a service pack with updated Microsoft classes and you find that the base class now also features a virtual method CalcResult, but with vastly different semantics.
In C++, a recompile would automatically result in your method being an overload of the CalcResult method that’s also being called from the base class’s code. Since the whole purpose of the base class’s CalcResult is likely different from what you might have designed it for, bugs and inconsistencies are guaranteed at this point.
Solution: Must state intent when using inheritance
To avoid this problem, C# requires you to clearly state your intent when using inheritance. Overloading virtual methods is never automatic in C#. To override a virtual function you must declare your specialized method with the override keyword, clearly stating your intent.
If you want to state that a method in your class explicitly hides a base class definition and starts a new virtual method hierarchy (since, otherwise, classes derived from your class could still choose to override your base class’s method) you state this with the new virtual keyword.
By the way, an important side effect of C#’s run-time system being .NET is that class library versions with different signatures and class layouts do not automatically force you to recompile the world or let your application tank right from the start. It just works.
Section 2: Elements of C#
[pic]
Goodies: XML Comments
Consistent, intrinsic way to create doc from code
For many languages there do exist utilities that are able to extract documentation from the source code. However, these tools require an external parser to be written and maintained, and each tool requires a different format and syntax for source code comments to be extracted.
The C# language and compiler has this feature already built-in and therefore provides a consistent way to create and extract documentation from source code as XML.
Triple-slash “///” comments are exported
Each comment starting with a triple forward slash is considered a documentation comment.
Extract full documentation during compile with /doc
If you use the /doc command-line switch and specify an output file, the C# compiler will extract all triple-slash comments and write them into an XML output stream that is structured using the code structure and layout.
Comes with predefined schema
To further standardize the comments, C# defines a standard schema that can be used to make documentation very consistent across projects. The schema allows for description of virtually any element of a declaration in a distinct way, yielding a well-structured XML-based documentation file.
The resulting XML data can later be transformed into any document format using XSL transformations or be submitted to XML-based repositories.
Section 3: The Tools
[pic]
Section 3: The Tools
The following section will provide a brief overview on the tools you need to build C# applications.
.NET Framework SDK—all you need to build applications
The .NET Framework software development kit (SDK) contains all basic tools and documentation to build .NET applications—including the compiler for C#, a visual debugger, and the Nmake build tool.
Visual —the productivity rocket
Visual , Microsoft’s premium development environment, is optimised for C# development with code wizards and templates and an automatic, smart help system.
Section 3: The Tools
[pic]
.NET Framework SDK
Contains C# compiler (plus compilers for Visual , C++, and )
The C# compiler contained in the .NET Framework SDK is full featured and, like the other SDK compilers for Visual , C++, and , is identical to the one that powers Visual .
The compilers shipping with the .NET Framework SDK run from the command line.
Visual Debugger—GuiDebug
The .NET Framework SDK’s debugger is a visual tool built on Visual technology that provides great control and insight on .NET applications and allows you to explore the run-time metadata of any .NET application.
Tools
In addition, the SDK ships with a multitude of tools including the Nmake tool to create build configurations for larger projects, security configuration utilities, the IL Disassembler that allows you to explore any assembly’s metadata, a visual designer for Windows Forms applications, and additional useful utilities.
Free for everyone
And a true “Microsoft first” about all this is, that the .NET Framework SDK is actually free for everyone to download and use; including the compilers.
Section 3: The Tools
[pic]
Visual
Built on the .NET Framework SDK
The next generation of Microsoft Visual Studio® is the integrated development environment for the .NET Framework SDK and, of course, also the evolutionary environment for building COM-based applications.
Reinvention of the Visual Studio idea
Visual Studio builds on the original idea to provide the most productive development environment. It also realizes the vision of having all Microsoft languages sharing a single and consistent development environment with shared tools for database creation and object modelling.
Using the .NET Framework common language runtime, you can have projects with multiple languages, choosing the right language for each particular task.
To get you up to speed in the new world of the .NET Framework, Visual Studio includes Dynamic Help, which anticipates questions you may want to ask as you are writing your code, and Intellisense® code completion, which helps you produce code more quickly.
Highest productivity for all
With a balance between support for rapid application development and being an excellent solution for co-developing large projects, Visual provides the highest productivity for every developer.
Section 4: Putting It All Together
[pic]
Section 4: Putting It All Together
Samples
In this final section we will see the traditional “Hello World!” example that every developer getting used to a new language or platform is usually taught.
After checking off this necessity, we will enter the world of Duwamish books, a full online bookstore built with C#, , and .
Section 4: Putting It All Together
[pic]
Hello World
This is a minimal C# application designed to write “Hello World!” to the system console.
Section 4: Putting It All Together
[pic]
Hello World Anatomy
Contained in its own namespace
It is quite obvious—and, by now, expected—that the application is implemented in its own namespace.
References other namespaces with “using”
To access the functionality of the Console class that allows us to write to the system console, we are pulling in all declarations of the System namespace (this doesn’t recursively include System’s subnamespaces, though)
Declares a publicly accessible application class
All code in C# must be contained in classes, so it is not surprising that the application itself is a class.
Entry point is “static int Main( … )”
The application’s entry point is a static method with a fixed signature and the default name Main.
Writes “Hello World!” to the system console
To keep things simple, we call the (also static) method WriteLine on the Console class to write “Hello World!” to the console and exit.
Summary
[pic]
Summary
Let us summarize what we have learned in this session:
C# builds on the .NET Framework component model
The C# language builds on the .NET Framework component model, which takes the best of COM+ and adds several important aspects in a evolutionary development of Microsoft’s component architecture.
Implements lessons learned
C# is designed to produce robust applications by eliminating common bug sources of the current C language family members. It also makes code easier to read and write and therefore easier to maintain.
New language with familiar structure
Although C# is a new language in many aspects that you have learned today, it is still familiar in syntax and a true member of the C-language family with its power of expression. Yet, it is much more straightforward in its design and easier to learn for any programmer.
Fully object oriented
C# is also fully object oriented (everything is an object), while the clear distinction between reference and value types allows for writing applications with optimum performance.
Optimized for the .NET Framework
Lastly, the C# language allows the most native and direct access to the power of the .NET platform.
Appendix: To C# from Visual Basic
[pic]
To C# from Visual Basic
This Appendix contains additional optional content for Visual Basic developers who want to switch from Visual Basic 6.0 to the C# language. The goal of the following eight slides is to present the “C” language family syntax to a Visual Basic developer audience, not necessarily to compare the languages Visual Basic 6.0 to C#.
Appendix B: To C# from Visual Basic
[pic]
C
Welcome to the C language family. Since its first publication through The C Programming Language by the legendary Dennis Ritchie and Brian Kernighan in 1974, the C language and its many derivatives, amongst them favourites like Objective C, C++, Java, and now C#, the C language has established itself as the most popular development choice for low-level and large-scale projects on virtually all operating system platforms. In fact, the bulk of most of today’s operating systems including Microsoft Windows 2000 are written in some variant of the C language.
The language C# inherits many of the core principles of the C language and most of those which made the language family so vastly popular.
If you have been writing applications in Visual Basic or some variant of Pascal until today, it would not be surprising if you were shocked or at least a bit irritated by the “C way” of expressing programs.
When we talk about C in this context, we really mean C# in the end, but since many of the initial remarks really apply to all C language family members, we stick to the term “C” whenever something generically applies to all of the languages, and we will mention C# directly if we have C# specifics at hand.
Core principles: Be brief. Be expressive.
Most of that irritation stems from C’s brevity. As a Visual Basic programmer you are accustomed to a very explicit style of programming where almost everything is expressed in clear words. C on the other hand is really written for the lazy programmer or the one who has to juggle a lot of code. You will find that an average C language family program is in the end a lot shorter that a Visual Basic program. Once you get used to the syntax it is even easier to grasp, since the only elements that really stick out from the very brief structural elements is what you most care about: your logic.
Core element: “{“ The Block “}”
The most important element in C is the block. A block is typically a group of related statements that are executed within a certain scope. Such a scope may be a method or a conditional execution path following an if statement or the code that is going to be repeatedly executed within a loop.
For code blocks, the block also implies scoping for variables. All variables that are declared within a block are only valid within this and all nested blocks and cannot be referenced or used outside the block.
Other uses of the block pattern are declarations of complex data types like structures (that is what you used the Type in Visual Basic 6.0 for or the RECORD in Pascal) or classes. Immediately following the declaration of either a struct or a class follows a block that contains all relevant definitions.
The block delimiters are the opening “{“ and the closing “}” braces.
Appendix B: To C# from Visual Basic
[pic]
Statements
All statements (“do that!”) are inside blocks
Simply speaking, statements are all language constructs that cause something to be done. They can only exist within a code block; that is, inside a method or a nested block. Each statement must be terminated with a semicolon.
Unlike Visual Basic, white space characters, line breaks, or any other formatting do not have any significance in the C languages. You can either consistently put many statements on one line, each properly terminated by its semicolon (in Visual Basic you use the colon “:” to separate statements on a line and use a line break for statements on consecutive lines), or you can just arbitrarily split the code over multiple lines as you need it, without having to explicitly state that intent (In Visual Basic you must use the continuation character “_” for this).
It is not necessarily good style to spread out statements over too many lines, but it allows for a more flexible programming style.
Some people take this a little further and do things as shown in the rightmost example, which is indeed a perfectly valid “C” program and won the “Best Layout” category in the 15th annual obfuscated C contest (). Of course, this is an example of how you should not do things, but shows at the same time how much freedom and flexibility the C language family gives you to express your intent when writing applications.
Appendix B: To C# from Visual Basic
[pic]
Declaration Principles
Core declaration principle: “What then who”
Every time you declare a variable, a class, or a structure in C, you will follow a very simple pattern: “what then who.”
What: data type or declaration keyword
First you state what you are going to express by either using a declaration keyword or a combination thereof or one of the predefined or user defined types.
If you start out with public struct then you state to the compiler that what follows is a, guess what, public struct. If you start with string then you indicate that you want to declare a variable of type string.
Who: user-defined identifier
Immediately following the “what” is the “who.” That’s where you name the new element that you intend to create. So, a public class Person or a public struct Point would be just what you expect them to be. An int Counter is an integer variable named Counter.
So, even if it is very brief and there are no supporting keywords or structural hints, it is very clear what the purpose is.
Two important issues that are you should be aware of:
• All identifiers must begin with a letter or the underscore character, may have arbitrary length, and may also contain numbers.
• Very important: All identifiers are case sensitive. Two variables A and a are not the same.
Appendix B: To C# from Visual Basic
[pic]
Operators
The “everything is brief” mantra continues with the operators. Except for the common arithmetic operators for the four basic mathematical operations and the greater/equal, less/equal operators, all operators are different from Visual Basic.
Arithmetic
The main binary arithmetic operations that expect two operands are the same as in Visual Basic. Unique is the modulo operator (remainder from an integer division), which is the percent sign (%) instead of the mod operator of Visual Basic.
The unary operators -- and ++ are the best example for how much you can express with little on a tiny space. ++ increments an ordinal value (like an integer) by 1 and -- decrements it by one. There are also some very nice and intended side effects caused by how you use the operators, but this would take us too far here.
Logical
The logical operators use special characters as well. A logical AND is expressed with two ampersands (&&), an OR with two pipes (||), and the unary NOT (always a prefix) is the exclamation point (!).
Compared to the simplicity of Visual Basic you may hate this at first, but in the end it really helps to make your code more readable with complex expressions, since it allows a clear separation between identifiers and objects and the respective operation. Explicit keywords tend to pollute complex expressions in a way that you cannot grasp at first glance what they are good for and that is key to keeping large applications in check.
Bitwise
If you want to combine integer values bit-by-bit you can use the bitwise operators for AND (&), OR (|), XOR (^), and the bitwise NOT (~), which reverses all bits in an expression.
Relational
The relational operators have one element that you will really need to get used to coming from Visual Basic. The equality operator is a double equal sign (==). In fact, many languages make a clear distinction between assignment and equality. In Pascal you assign using the := operator and compare with a simple equal sign. Visual Basic simply derives the intent from where the operator is used and therefore imposes some limits on what expressions you can use.
The “not equal” operator follows the model of the logical operator NOT (!) and is expressed as NOT (!) EQUAL (=), that is, !=.
Luckily, all other relational operators are as you know them.
Appendix B: To C# from Visual Basic
[pic]
Expressions
Boolean expressions
Boolean expressions in C# evaluate to true or false, which are both keywords built into the language. All relational or logical expressions are Boolean.
Arithmetic expressions
Arithmetic expressions are used and evaluated just as in Visual Basic.
Assignment
You probably would not expect any surprises on the assignment operator “=”, but here it is another instance of “brevity rules.”
Basic assignments of variables work just as expected, but you can also assign values to variables right at the point of declaration and you can even perform operations at assignment.
The expression a += 4 is shorthand expression for assigning the value a + 4 to a. This is very cool. Otherwise it does not occur often in day-to-day programming.
Appendix B: To C# from Visual Basic
[pic]
Flow Control
Conditional execution of code blocks
The mantra continues: “everything is brief.” This is also valid for the conditional execution expression if. You do not need a Then or End If. You use the keyword if followed by a Boolean condition contained in parentheses and the code block that is to be executed if the condition is true. If you also want to execute code if the condition is not met, you append the keyword else followed by another code block.
Selective execution of code blocks
With the switch statement you can selectively execute code based on a certain state of a variable or return value of a method call.
The statement begins with the switch keyword and the test expression enclosed in parentheses. The following block has one or more “case” labels, each followed by a constant expression. If the test expression and the constant value match (equality) the statements following the label are executed. The statement sequence must be followed by a break; statement.
If you want to handle all other cases for which you do not have an explicit case label, you can use the default label.
Appendix B: To C# from Visual Basic
[pic]
Loops
Counted loops
The for loop of C# is significantly different from Visual Basic: quite a bit more complicated and endlessly more powerful.
Every for loop has a precondition, a test condition, and an increment statement that are expressed, enclosed in parentheses and separated by semicolons, after the for keyword.
In the precondition, you typically set the initial value for your loop variable, but you may just about do anything you like here including leaving the expression blank. If you want to use two counter variables at the same time you can even initialize them both here (a=0,q=10—separated by the comma operator that allows you to simply concatenate two actions into one statement).
The loop is executed as long as the test condition evaluates to true. It is easy to implement simple counting loops with that, but you can actually use Boolean expression here and thus create pretty powerful loops.
The increment expression is executed exactly once before every loop (except the first one when the precondition is executed) and you can use this to change your counter variable or, again, do anything else that makes sense for you here.
While loops
While loops are much simpler: the keyword while followed by a Boolean expression that is evaluated before every loop, and a code block that is executed on each run. If you want to exit a while loop under special conditions you can always use a break; statement anywhere within the loop. To terminate the current block execution and proceed to the next run of the loop you can use the continue; statement. Both can also be used with for, but are more often used with while loops.
A while loop with a condition that is being executed at the end of each loop also exists with the do … while expression, which is similarly easy to express. Here you prefix the code block with a do to announce the following while statement and express the condition just as with the “normal” while loop.
Appendix B: To C# from Visual Basic
[pic]
Other Noteworthy Things…
Here are some other noteworthy things that should be mentioned to help you understanding the C# language a bit better:
The data type “void” means “no type”
The data type void is really no data type but a replacement for “nothing” whenever a type is expected in a method expression. A method that returns void returns nothing, and a method with a void argument expects nothing. In C, the keyword also has some other uses that we do not have to consider here.
C has pointers. In C# you do not need them
The C language’s greatest challenge for every developer is to master pointers. C# is a “mostly no pointers” language and only allows them if you really want them and explicitly tell the compiler through a keyword that you want to use them. Simply speaking: With C#, you don’t want to use them, so don’t worry about it.
One of the reasons for pointer usage in C is to allow by-reference parameters. C# has an explicit ref keyword to enable such parameters and otherwise makes a clear distinction between value and reference types.
Very few keywords and intrinsic functionality
Like its parent C, C# also relies heavily on run-time libraries. The C# language by itself is surprisingly “thin” and does not have more than two hands full of keywords. Everything else comes from the run-time libraries. Among the things that you may expect the language to incorporate, but which are actually missing, are even some of the more fundamental things. For example, a^b is expressed by means of the run-time library in C#: Math.Pow(a,b).
Legal Notices
[pic]
Unpublished work. © 2001 Microsoft Corporation. All rights reserved.
Microsoft, IntelliSense, JScript, Visual Basic, Visual Studio, Win32, and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.
The names of actual companies and products mentioned herein may be the trademarks of their respective owners.
................
................
In order to avoid copyright disputes, this page is only a partial summary.
To fulfill the demand for quickly locating and searching documents.
It is intelligent file search solution for home and business.
Related searches
- c reactive protein level 30
- c reactive protein level chart
- does emergen c work
- is emergen c good for you
- c words to describe someone
- c reactive protein high
- c reactive protein high treatment
- c reactive protein elevated autoimmune
- does emergen c really work
- what is c reactive protein levels mean
- high c reactive protein autoimmune
- elevated c reactive protein foods