C


C#

Like .NET itself, C# has raised a fair amount of discussion, much of it based around raising questions such as "Another language? Why?" and "Isn't it just Java?". To understand why a new language has been introduced, think about what Microsoft is trying to achieve with .NET. Some of the key ideas are:

  • Cross-language development.

  • A unified type system.

  • Extensibility and security.

  • Greater support for development tools.

These are not the only goals, nor are they specific reasons for creating a new language, but it was clear that to build the .NET Framework the existing languages wouldn't meet these requirements. C++, for example, isn't truly component oriented, and still has many hang-ups from the C language. Java is bound by its ownership by Sun (not to mention lawsuits) and is interpreted, which leads to performance problems. Object-oriented languages such as Smalltalk and Eiffel have the stigma of being considered obscure, and would need performance increases and structural changes.

Therefore, a new language was the simplest answer, but not so new, that it wouldn't feel familiar. You can think of C# as a member of the C/C++ family “ a fact that's not surprising, since the majority of development at Microsoft is done in these languages. As such, C# contains the best features of C++, but leaves out all of the bits that aren't required for a language to be part of the framework (such as typedefs , templates, and so on). Leaving out functionality hasn't been a hindrance, rather, it has made the language simpler to use and more efficient. In addition, it's not just a language being pushed on the public “ ASP.NET is entirely written in C#.

Note

If you're a Visual Basic or VBScript programmer trying out C# for the first time, there's one really important thing to note: C# is case-sensitive.

Classes

Even though C# is more like C and C++, Visual Basic or VBScript programmers won't have too much trouble with this new language. Classes are defined using the following syntax:

  [public  protected  internal  protected internal  private     abstract  sealed ] class  className    {   }  

Let's look at the keywords here in more detail:

Keyword

Description

public

The class is publicly accessible.

protected

The class is only accessible from the containing class or types derived from the containing class.

internal

The class is only accessible from this program. Equivalent to Friend in Visual Basic.

protected internal

The class is only accessible from this program or types derived from the containing class. Equivalent to Protected Friend in Visual Basic.

private

The class is only accessible from within the containing class.

abstract

This class is an abstract class, and the class members must be implemented by inheriting classes. Equivalent to MustInherit in Visual Basic.

sealed

No further inheritance is allowed from this class. Equivalent to NotInheritable in Visual Basic.

For example:

  public class Calculator   {   // implementation goes here   }  

Methods

In C# there is no direct distinction between a Sub and a Function , and members are just implemented as functions (that may or may not return data). The syntax is:

 [ public  protected  internal  protected internal  private  static  virtual  override  abstract  extern ]   [  type  void ]  memberName  ([  parameters  ])   {   }  

The various keywords are described as follows :

Keyword

Description

public

The member is publicly accessible.

protected

The member is only accessible from the containing class or types derived from the containing member.

internal

The member is only accessible from this program. Equivalent to Friend in Visual Basic.

protected internal

The member is only accessible from this program, or types derived from the containing member. Equivalent to Protected Friend in Visual Basic.

private

The member is only accessible from within the containing member.

static

The member is shared by all instances of the class, and it exists independently of a class instance. Equivalent to Shared in Visual Basic.

virtual

The member can be overridden by a sub-class.

override

The member overrides an identically named member from a base class, with the same signature. The base class member must be defined as virtual , abstract or override .

abstract

This member is an abstract member, and must be implemented by a subclass.

extern

The member is implemented in an external assembly.

For example:

  public class calculator   {   public double Add(double op1, double op2)   {   return op1 + op2;   }   }  

For a method that does not return a result, we declare the type as void :

  public void updateSomething()   {   }  

Properties

Properties in C# are very similar to Visual Basic .NET, and can be implemented as public member variables or by using the property accessors. For example, the following class uses public variables :

 public class calculator {  public double Op1;   public double Op2;  public double Add()    {       return Op1 + Op2;    } } 

The alternative (and preferred) approach is to use property accessors. For example:

  public class calculator   {   private double _op1;   private double _op2;     public double Operand1   {   get   {   return _op1;   }   set   {   _op1 = value;   }   }     public double Operand2   {   get   {   return _op2;   }   set   {   _op2 = value;   }   }     }  

Unlike Visual Basic, there are no specific keywords to identify read-only and write-only properties. If only the get accessor is provided, the property is read-only , and if only the set accessor is provided, the property is write-only . Both accessors imply a read-write property.

Constructors

Rather than using New for constructors, the C# syntax is to use a method with the same name as the class. For example:

  public class person   {   private string _firstName;   private string _lastName;     public person() {}     public person(string firstName, string lastName)   {   _firstName = firstName;   _lastName = lastName;   }   public string FirstName   {   // property accessors here   }     public string LastName   {   // property accessors here   }   }  

Destructors

For destructors there is no Destruct keyword. This functionality is provided by a method with the same name as the class, but with a tilde ( ~ ) preceding it. For example:

 public class person {    private string _firstName;    private string _lastName;         public person() {}         public person(string firstName, string lastName) { }  ~person()   {   // destructor code here   }  } 
Note

Like in Visual Basic .NET, destructors in C# are called by the garbage collector, and are not guaranteed to be executed at the time you destroy the class.

Inheritance

Inheritance in C# looks more like C++, where a colon ( : ) is used to separate the class and the base class. For example:

  public class programmer : person   {   private int _avgHoursSleepPerNight;     public programmer(): base()   {   }     public programmer(string firstName, string lastName):   base(firstName, lastName)   {   }   public programmer(string firstName, string lastName, int hoursSleep):   base(firstName, lastName)   {   _avgHoursSleepPerNight = hoursSleep;   }   public int AvgHoursSleepPerNight   {   get { return _avgHoursSleepPerNight; }   set { _avgHoursSleepPerNight = value; }   }   }  

The class definition defines that the class is called programmer and the base class is called person :

 public class programmer : person { 

Next, you need to provide the constructors. Here specify the same constructors as the base class, and use the same inheritance syntax ( : ) to indicate that this method inherits its implementation from the base class. Any parameters should be passed to the base class constructor:

 public programmer(): base() { }      public programmer(string firstName, string lastName):        base(firstName, lastName) { } 

To declare an additional constructor, follow the same rules, invoking the base constructor, but also providing additional functionality:

 public programmer(string firstName, string lastName, int hoursSleep):        base(firstName, lastName)    {       _avgHoursSleepPerNight = hoursSleep;    } 

Finally, you have the new property:

 public int AvgHoursSleepPerNight    {       get { return _avgHoursSleepPerNight; }       set { _avgHoursSleepPerNight = value; }    } } 

The value keyword is implemented automatically by the CLR, providing the property with the supplied value from the calling program.

Interfaces

Interfaces work the same as in Visual Basic .NET, providing an immutable contract to the external world.

To create an interface, use the interface construct. For example:

 public interface IPerson {    string FirstName(get; set;)    string LastName(get; set;)         string FullName(); } 

To derive a class from an interface, use the same method as inheritance:

 public class Person : IPerson {    private string _firstName;    private string _lastName;         public string FirstName()    {       // implementation goes here    }         public string LastName()    {       // implementation goes here    }         public string FullName()    {       return _firstName + " " + _lastName;    } } 

Notice that unlike Visual Basic .NET, only the class needs to specify the interface inheritance.

References

References use the same method as Visual Basic .NET, but with the keyword using instead of Imports:

  using System;   using MyComponent;  

It's also possible to alias references using the following syntax:

  using  aliasName  =  Namespace;   

If an alias is used, the alias must be included in references to classes that the namespace contains. For example, if you have a namespace called MyComponent containing a class called MyClass , and import the namespace like this:

  using foo = MyComponent;  

You can't then access the class like this:

  MyClass comp = MyClass  

You have to use the following syntax:

  foo.MyClass comp = foo.MyClass  

Exception Handling

The try catch finally combo is another way of performing exception handling in C#, using the following syntax:

  try   {   // code block to try   }   [catch[(type exception)]   {   // code block to run if the exception matches the type above   }]   catch[(type exception)]   {   // code block to run if the exception matches the type above   }   finally   {   ' code that always runs, whether or not   ' an exception was caught   }  

For example:

  try   {   // connect to a database and   // retrieve some data   // ... code left out for clarity ...   }   catch(SQLException exSQL)   {   ErrorLabel.Text = "SQL Error: " + exSQL.ToString();   }   catch(Exception ex)   {   ErrorLabel.Text = "Other error: " + ex.ToString();   }   finally   {   FinishedLabel.Text = "Finished";   }  

The throw statement can be used to raise errors, even when in try catch blocks. For example:

  try   {   // some code here   }   catch(SQLException exSQL)   {   if (some expression)   throw(exSQL);   }  

XML Documentation

One great feature that C# has over Visual Basic is the ability to include inline documentation. This is done by placing a set of XML tags at various places in code, and then adding a compiler directive to pull out the comments. For example:

 using System;      namespace peopleCS {  ///<remarks>   ///The <c>programmer</c>class defines the salient   ///attributes of every fine programmer.   ///<seealso cref="person">Inherits from person</seealso>   ///</remarks>  public class programmer : person    {       private int _avgHoursSleepPerNight;  ///<summary>Default constructor</summary>  public programmer(): base()       { }  ///<summary>Constructor using first and last names</summary>     ///<param name="firstName">The first name of the programmer</param>     ///<param name="lastName">The last name of the programmer</param>     ///<seealso cref="string"/>     public programmer(string firstName, string lastName):   base(firstName, lastName)   { }     ///<summary>Constructor using first and last names and     ///the hours of sleep</summary>     ///<param name="firstName">The first name of the programmer</param>     ///<param name="lastName">The last name of the programmer</param>     ///<param name="hoursSleep">The average number of hours of sleep</param>     ///<seealso cref="string"/>     ///<seealso cref="int"/>  public programmer(string firstName, string lastName, int hoursSleep):              base(firstName, lastName)       {          _avgHoursSleepPerNight = hoursSleep;       }  ///<value>Defines the average number of hours of sleep.</value>  public int AvgHoursSleepPerNight            {          get { return _avgHoursSleepPerNight; }          set { _avgHoursSleepPerNight = value; }       }    } } 
Note

The XML tags are placed after three /// characters “ not to be confused with two, as used by comments.

The tags are as follows:

Tag

Description

c

Text that indicates inline code.

code

Multiple lines of code, such as a sample.

example

Description of a code sample.

exception

Indicates an exception class. Additionally, the attribute cref can be used to reference another type (such as the exception type). This reference is checked against the imported libraries.

include

Allows XML documentation to be retrieved from another file.

list

Indicates a list of items. The type attribute can be one of:

bullet , for bulleted lists

number , for numbered lists

table , for a table

You can use a listheader element to define headings, and an item element to define the items in the list. Each of these can contain two elements: item for the item being listed, and description .

para

Allows paragraph definitions within other tags.

param

Describes the parameter of a method. The name attribute should match the name of the parameter.

paramref

Used to indicate references for parameters.

permission

Describes the permissions required to access the member. The cref can be used to reference another type (such as the security permission type). This reference is checked against the imported libraries.

remarks

Overview information about the class or type.

returns

The return value of a method.

see

The attribute cref is used to reference another type (such as a related member). This reference is checked against the imported libraries.

seealso

The attribute cref is used to reference another type (such as a related member), to be documented in the See Also section. This reference is checked against the imported libraries.

summary

Description of a member or type.

value

Description of a property.

In Visual Studio, these tags can be processed to form HTML pages that become part of the project documentation. Outside Visual Studio, you can produce an XML file for the comments by using the /doc compiler switch (more on these in The .NET Language Compilers section), which produces the file as follows:

  <?xml version="1.0"?>   <doc>     <assembly>   <name>PeopleCS</name>   </assembly>     <members>     <member name="T:peopleCS.programmer">   <remarks>   The <c>programmer</c>class defines the salient   attributes of every fine programmer.   <seealso cref="T:peopleCS.person">Inherits from person</seealso>   </remarks>   </member>     <member name="M:peopleCS.programmer.#ctor">   <summary>Default constructor</summary>   </member>     <member name="M:peopleCS.programmer.#ctor(System.String,System.String)">   <summary>Constructor using first and last names</summary>   <param name="firstName">The first name of the programmer</param>   <param name="lastName">The last name of the programmer</param>   <seealso cref="T:System.String"/>   </member>     <member name="M:peopleCS.programmer.#ctor(System.String,   System.String,System.Int32)">   <summary>Constructor using first and last   names and the hours of sleep</summary>   <param name="firstName">The first name of the programmer</param>   <param name="lastName">The last name of the programmer</param>   <param name="hoursSleep">The average number of hours of sleep</param>   <seealso cref="T:System.String"/>   <seealso cref="T:System.Int32"/>   </member>     <member name="P:peopleCS.programmer.AvgHoursSleepPerNight">   <value>Defines the average number of hours of sleep.</value>   </member>     </members>     </doc>  

The compiler automatically includes the namespace and builds tags for the member names. The members are given a fully qualified name starting with one of the following prefixes:

Prefix

Description

N

Namespace

T

Type: Class , Interface , Struct , Enum , or Delegate

F

Field

P

Property (including indexers)

M

Method (including constructors)

E

Event

!

Error string if links cannot be resolved

You could then use an XSLT stylesheet, or XML processing code to style this into your own documentation. You could also add your own XML elements to the class descriptions, and these would be extracted along with the predefined elements.

Unsafe Code

Although C# is part of the managed code environment, Microsoft has realized that sometimes developers need total control, such as when performance is an issue, when dealing with binary structures, or for some advanced COM support. Under these circumstances, you are able to use C# code in an unsafe manner, using pointers, unsafe casts, and so on.

As an ASP.NET developer it's unlikely you'll ever need this, but knowing it's available gives you the flexibility to choose, should the need arise.

Operator Overloading

C# is the only one of the supplied languages that supports operator overloading. This works in the same way as method overloading, except for operators. The reason for this is to allow the standard operators to be used on objects such as classes.

The classic example given is a class for handling complex numbers , which have a real and imaginary part (stored as integers). Imagine a class that has two properties for these two parts , and a constructor that takes two arguments to match the properties:

  CNumber c1 = new CNumber(12, 4);   CNumber c2 = new CNumber(5, 6);  

When performing addition on complex numbers, you must add the real part and imaginary part independently of each other, and might consider creating this method:

  public CNumber Add(CNumber c1, CNumber c2)   {   return new CNumber(c1.real + c2.real, c1.imag + c2.imag);   }  

You could then call this by:

  CNumber c3 = CNumber.Add(c1, c2);  

There's nothing wrong with that per se, but it would be far better to use:

  CNumber c3 = c1 + c2;  

To achieve this, you would have to overload the + operator:

  public static CNumber operator +(CNumber c1, CNumber c2);   {   return new CNumber(c1.real + c2.real, c1.imag + c2.imag);   }  

This provides a much more intuitive way of developing, and is especially useful when building class libraries for other developers.

Note

For more details on C#, see Professional C# , ISBN 0-7645-4398-9, from Wrox Press.




Professional ASP. NET 1.1
Professional ASP.NET MVC 1.0 (Wrox Programmer to Programmer)
ISBN: 0470384611
EAN: 2147483647
Year: 2006
Pages: 243

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