Download Evaluation of C# Language

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Functional programming wikipedia , lookup

Ada (programming language) wikipedia , lookup

Indentation style wikipedia , lookup

Swift (programming language) wikipedia , lookup

Programming language wikipedia , lookup

Scala (programming language) wikipedia , lookup

Reactive programming wikipedia , lookup

Falcon (programming language) wikipedia , lookup

Design Patterns wikipedia , lookup

Class (computer programming) wikipedia , lookup

Component Object Model wikipedia , lookup

Standard ML wikipedia , lookup

Java syntax wikipedia , lookup

Object-relational impedance mismatch wikipedia , lookup

Name mangling wikipedia , lookup

Abstraction (computer science) wikipedia , lookup

Covariance and contravariance (computer science) wikipedia , lookup

Object-oriented programming wikipedia , lookup

Structured programming wikipedia , lookup

C++ wikipedia , lookup

C syntax wikipedia , lookup

Go (programming language) wikipedia , lookup

C Sharp syntax wikipedia , lookup

C Sharp (programming language) wikipedia , lookup

Transcript
Meg Yahl
CSC 415 Term Paper
11/20/2012
C#
Megan Yahl
CSC 415: Programming Languages
Dr. Lyle
November 20, 2012
Page | 1
Meg Yahl
CSC 415 Term Paper
11/20/2012
History of C#
Naming
The C# programming language is a powerful language built on the .NET framework.
Microsoft’s Anders Hejlsberg, often referred to as the “father of C#,” led the team that was
responsible for the creation of this COOL language, as it was known at the time. According to
Hejlsberg, the team seriously considered keeping the name COOL, which stands for “C-like
Object Oriented Language,” but couldn’t due to trademark conflicts (Hejlsberg, The A-Z of
Programming Languages: C#). Instead, they settled on C#, which also had a bit of word play to
it. In music, the sharp sign raises a note by a half step. This could be seen as being “a step above”
C, so to speak. When asked about the new name, Hejlsberg stated, “We sort of liked the notion
of having an inherent reference to C in there, and a little word play on C++, as you can sort of
view the sharp sign as four pluses, so it’s C++++. And the musical aspect was interesting too"
(Hejlsberg, The A-Z of Programming Languages: C#).
Design
In an interview with Naomi Hamilton, a writer for Computerworld.com, Hejlsberg
explained some of the design goals in developing C#. The overall goal was to “create a first class
modern language on [the Common Runtime Language] platform that would appeal to the curly
braces crowd: the C++ programmers of the world at the time, and competitively, the Java
programmers” (Hejlsberg, The A-Z of Programming Languages: C#). This design involved
“support for the next level up from object oriented programming to component-based
programming” (Hejlsberg, The A-Z of Programming Languages: C#). Versioning was also an
Page | 2
Meg Yahl
CSC 415 Term Paper
11/20/2012
important consideration to Hejlsberg and his team. C# was designed so that it would version
well, without new features breaking old code.
Identifiers, Bindings, and Scopes
Identifiers
According to Ben and Joseph Albahari, authors of C# 4.0 in a Nutshell, “Identifiers are
names that programmers choose for their classes, methods, variables, and so on” (Albahari 10).
An identifier must begin with a letter or an underscore, and it cannot have the same name as a
keyword, with one exception. If an identifier has the same name as a keyword, the former must
be prefixed by the @ symbol. However, this should be avoided if at all possible due to its impact
on readability. C# identifiers are case sensitive, and while there is not an enforced rule dictating
proper case format, there is a common convention that should be followed. Typically,
“parameters, local variables, and private fields should be in camel case (e.g., myVariable), and
all other identifiers should be in Pascal case (e.g., MyMethod)” (Albahari 10).
Bindings
C#, for the most part, is a statically typed language. With the release of C# 4.0, dynamic
binding became available. Robert Sebesta, author of Concepts of Programming Languages,
describes binding as “an association between an attribute and an entity, such as between a
variable and its type or value, or between an operation and a symbol” (Sebesta 209). The
difference between static and dynamic binding is the binding time, or the time at which the
binding happens. Static binding happens at compile time, while dynamic binding happens at
runtime. The Albahari brothers state that “Calling an object dynamically is useful in scenarios
Page | 3
Meg Yahl
CSC 415 Term Paper
11/20/2012
that would otherwise require complicated reflection code. Dynamic binding is also useful when
interoperating with dynamic languages and COM components” (Albahari 5).
Scopes
According to Sebesta, scope is the range of statements in which a variable, class,
package, or namespace can be referenced (Sebesta 218). There are three main ranges of scope:
local, nonlocal, and global (a special case of nonlocal). To illustrate this, assume there exist
variables varA, varB, and varC, a code block foo, and a code block bar. Block bar is nested
within block foo. If varA is declared within block bar, then varA is local to block bar. If varB is
declared within block foo, then varB is local to block foo and nonlocal to block bar. If varC is
declared outside all methods in the program, then varC is said to be global, and is visible to foo,
bar, and all other code blocks and methods.
Data Types
C# is a strongly typed language. This means that “every variable and constant has a type,
as does every expression that evaluates to a value” (Microsoft Corporation). Additionally, “every
method signature specifies a type for each input parameter and for the return value” (Microsoft
Corporation). When designing the language, Anders Hejlsberg wanted a “unified and extensible
type system” (Hejlsberg, The A-Z of Programming Languages: C#). He claims that this system is
great for teaching because everything is an object. This statement has sparked quite a heated
debate in the C# developer community, as it is mostly true, but a bit misleading. The debate
revolves around a slightly modified version of Hejlsberg’s statement. The modified version
essentially states that “in C# every type derives from object” (Lippert). Eric Lippert is a principal
developer on the C# compiler team, and he counters this statement on his blog. After a lengthy
Page | 4
Meg Yahl
CSC 415 Term Paper
11/20/2012
explanation, Lippert concludes that “every non-pointer type in C# is convertible to an object”
(Lippert).
Value Types
C# includes value types, reference types, generic type parameters, and pointer types. As
implied in the name, value types store actual data, or values. Value types include “all numeric
types, the char type, and the bool type, as well as custom struct and enum types” (Albahari 17).
Value types cannot contain the null value; however, “the nullable types feature does allow for
value types to be assigned to null” (Microsoft Corporation). Value types are directly accessed
without the need for a new operator. This is because “each value type has an implicit default
constructor that initializes the default value of that type” (Microsoft Corporation). Value types
can be represented both in boxed and unboxed form. Boxing is like taking the value type and
wrapping it up in a little box, which can then be treated like an object. Unboxing simply reverses
this process. This concept is important to the earlier point that “every non-pointer type in C# is
convertible to an object” (Lippert).
As mentioned earlier, value types also include struct and enum types. A struct is
“typically used to encapsulate small groups of related variables” (Microsoft Corporation). Structs
may contain: constructors, constants, fields, methods, properties, indexers, operators, events, and
nested types (Microsoft Corporation). Finally, structs can “implement an interface, but they
cannot inherit from another struct” (Microsoft Corporation).
An enumeration is a data type defined by the user. It is “a distinct type consisting of a set
of named constants called the enumerator list” (Microsoft Corporation). Enumerations are useful
for providing “an efficient way to define a set of named integral constants that may be assigned
to a variable” (Microsoft Corporation). Both structs and enumerations help with readability since
Page | 5
Meg Yahl
CSC 415 Term Paper
11/20/2012
programmers are able to give clear names and structure to what may otherwise be difficult to
understand.
Reference Types
Reference types are made of an object and a reference to that object. Unlike value types,
a reference type stores references to the actual data instead of the data itself. This memory
handling is the fundamental difference between the two types. Programmers must use care with
reference types since “two or more reference type variables can refer to a single object in the
heap, allowing operations on one variable to affect the object referenced by the other variable”
(Afana). This can hurt the reliability of the language. Reference types include “all class, array,
delegate, and interface types” (Albahari 17).
Arrays use square brackets for declaration and indexing. Array indexes start at 0 and end
at one less than the array size. They are very efficient on memory because all the elements are
stored together in one block. C# supports multidimensional arrays, both rectangular and jagged.
Rectangular arrays, declared with ‘[,]’ after the type, are two-dimensional arrays with the same
length and width. Jagged arrays, declared with ‘[][]’ after the type, are arrays of arrays. Arrays
know their own length and also have a multitude of useful properties and methods accessible to
them via the System.Array class. According to Albahari, “all array indexing is bounds-checked
by the runtime” (Albahari 35).
Generic Types
Generics are useful for writing reusable code that can accommodate different types. C#
also achieves reusability via inheritance (which will be discussed later). According to Albahari,
“inheritance expresses reusability with a base type, [whereas] generics express reusability with a
Page | 6
Meg Yahl
CSC 415 Term Paper
11/20/2012
‘template’ that contains ‘placeholder’ types. Generics, when compared to inheritance, can
increase type safety and reduce casting and boxing” (Albahari 101).
Pointers
In C#, pointers are used to directly manipulate memory. They can only be used with
unsafe code. Albahari states that “pointer types are primarily useful for interoperability with C
APIs, but may also be used for accessing memory outside the managed heap or for performancecritical hotspots” (Albahari 170).
Expressions and Assignment Statements
Expressions
In mathematics, there is a fundamental difference between an equation and an expression.
An equation can be solved, whereas an expression only represents or evaluates to a value. An
expression can be simple, made up of either a constant or a variable. It can also be complex by
using operations to combine constants, variables, and other expressions. Expressions within
expressions are sometimes denoted with grouping symbols, such as parenthesis.
Expressions in C# work much like they do in mathematics. In C# there are primary
expressions, void expressions, and expression statements. Primary expressions “include
expressions composed of operators that are intrinsic to the basic plumbing of the language”
(Albahari 45). As the name implies, void expressions do not have a value. Because of this, void
expressions “cannot be used as an operand to build more complex expressions” (Albahari 45).
Operators
Operators are very important in C#. They “transform and combine expressions” (Albahari
12). There are many different operators in C# and each fits into a particular category. These
Page | 7
Meg Yahl
CSC 415 Term Paper
11/20/2012
categories (in descending order of operator precedence) include primary, unary, multiplicative,
additive, shift, relational and type testing, equality, logical AND, logical XOR, logical OR,
conditional AND, conditional OR, conditional, and assignment (Microsoft Corporation). Many
of these operators can also be overloaded.
Expression Statements
Expressions that can stand alone as valid statements are called expression statements.
They “must either change state or call something that might change state. Changing state
essentially means changing a variable” (Albahari 49). Expression statements include
“assignment expressions (including increment and decrement expressions), method call
expressions (both void and nonvoid), and object instantiation expressions” (Albahari 49). In C#,
the assignment operator is =. The assignment statement evaluates the expression on the right side
of the operator and assigns it to the variable on the left side. There are also compound
assignment operators, which are “syntactic shortcuts that combine assignment with another
operator” (Albahari). While these shortcuts improve writability, they can potentially hurt
readability.
Statement-Level Control Structures
According to Robert Sebesta, author of Concepts of Programming Languages, “a control
structure is a control statement and the collection of statements whose execution it controls”
(Sebesta 349). Control structures direct the flow of the program. They are intended to make
decisions and execute different statements depending on the result. There are three main types of
control structures in C#: selection, iteration, and unconditional branching, or jump statements. In
C#, most control expressions are specified in parentheses and must be of type Boolean.
Page | 8
Meg Yahl
CSC 415 Term Paper
11/20/2012
Jump Statements
The C# jump statements include break, continue, goto, return, and throw. The break
statement immediately “ends the execution of the body of an iteration or switch” (Albahari 55).
The continue statement immediately jumps to the end of a loop and starts the next iteration. The
goto statement is powerful and can quickly complicate code if used irresponsibly. Albahari says
that it allows code execution to jump to another label within the statement block. A label
statement is just a placeholder in a code block, denoted with a colon suffix. The goto caseconstant transfers execution to another case in a switch block (Albahari 55). Return statements
can appear anywhere in a nonvoid method. Their job is to exit the method and return an
expression of the method’s return type (Albahari 56). Throw statements detect the occurrence of
an error and throw the relevant exception, which is then handled by the programmer.
A key property of jump statements is that they “obey the reliability rules of try
statements” (Albahari 54). Specifically, “a jump out of a try block always executes the try’s
finally block before reaching the target of the jump, [and] a jump cannot be made from the inside
to the outside of a finally block” (Albahari 54). This is important in exception handling, which
will be discussed in further detail later.
A note on goto: When used irresponsibly, code can become nearly unreadable. It is for
this reason that many programmers have reserved goto as an absolute last resort, or even shunned
it altogether. The popular webcomic xkcd features a strip titled “GOTO,” in which the main
character debates restructuring the flow of his entire program, or using a goto. He chooses the
latter, and is subsequently attacked by a random velociraptor1.
Selection Statements
1
Illustrated in Item 1 of the Appendix
Page | 9
Meg Yahl
CSC 415 Term Paper
11/20/2012
Selection statements include the if-else construct and switch statement. The if-else
construct is present in many mainstream languages, and works similarly in C#. The Boolean
condition is specified in parenthesis, and the body of the construct is contained within curly
braces. Curly braces are optional when the body has only one statement to execute. The if
statement can be standalone or paired with a single else statement. It can also be paired with one
or more else if statements. The if-else construct can be nested as deeply as desired, though it can
quickly become complicated and difficult to read. The last else statement always belongs to the
last unpaired if statement. In this context, “unpaired” denotes the last if that does not already
have an else.
When the if-else construct has many else if statements, it may be better to utilize a switch
statement instead. A switch statement is “a control statement that selects a switch section to
execute from a list of candidates” (Microsoft Corporation). The first switch section is
functionally equivalent to an if statement. Any switch sections that follow are functionally
equivalent to an else if statement, with the exception of the default section. If present, the
default section must be the last section in the switch structure. It is functionally equivalent to an
else statement. At the end of each section, some sort of jump statement must be included to exit
the section. Because “C# does not allow execution to continue from one switch section to the
next” (Microsoft Corporation), the absence of a jump statement will cause an error. The switch
section to be executed is chosen by the value of the switch expression. This process is explained
by the Microsoft Corporation:
Each switch section contains one or more case labels and a list of one or more
statements. Each case label specifies a constant value. Control is transferred to the switch
section whose case label contains a constant value that matches the value of the switch
Page | 10
Meg Yahl
CSC 415 Term Paper
11/20/2012
expression. If no case label contains a matching value, control is transferred to
the default section, if there is one. If there is no default section, no action is taken and
control is transferred outside the switch statement.
While the syntax may sound complicated, it is actually much more readable in practice. Any
simplification in code, provided it has the same functionality, helps readability. Replacing
complicated if-else structures with switch statements is one way to enhance a program’s
readability.
Iteration
Loops allow repetition by executing a block of statements until a given condition is false.
Loops can be exited by break, goto, return, or throw statements. A continue statement jumps
straight to condition evaluation. There are four types of loops in C#. These include while, dowhile, for, and foreach. The loop body syntax is like that of the if-else construct. The while and
do-while loops have Boolean conditions in parenthesis after the while. They differ in that while
is pre-check and do-while is post-check. With a do-while loop, the body of the loop is
guaranteed to execute at least once, whereas the body of the while loop may not be executed at
all.
The for loop is designed to loop a specific number of times, then exit. They are especially
useful for iterating over arrays. There are three parts to a for loop: the initializer, the condition,
and the iterator. Each part is separated by a semicolon. Any of these expressions can be omitted
as long as both semicolons are present. However, omitting all parts causes an infinite loop. C#’s
for loops are interesting in that the initializer section can either declare and initialize a loop
variable, or it can contain any number of assignment statements, method invocations, prefix or
postfix increment or decrement expressions, object creations (using new), and await expressions
Page | 11
Meg Yahl
CSC 415 Term Paper
11/20/2012
(Microsoft Corporation). The iterator section can also contain any of the aforementioned
statement expressions. Between the two is the condition section, which “contains a Boolean
expression that’s evaluated to determine whether the loop should exit or should run again”
(Microsoft Corporation). The body of the loop is like that of the selection statements.
The foreach loop is designed specifically for arrays and object collections. Instead of
iterating a specified number of times, it iterates through the entire array or collection provided to
it. Like any other loop, the foreach loop can be broken out of by using a jump statement. While
the foreach loop can do a number of things to the array or collection, it “cannot be used to add or
remove items from the source collection” (Microsoft Corporation).
Subprograms (Methods)
In C#, subprograms in general are referred to as methods. Methods can have any type,
including user-defined types and void.
Parameter passing
C# has several ways to pass parameters to a method. The semantics of this include in
mode, out mode, and inout mode. In mode parameters take in data from the actual parameters.
Out mode parameters send out data to the actual parameters. Inout parameters both take in data
and send out data. These semantic models are implemented by pass-by-value, pass-by-result,
pass-by-value-result, and pass-by-reference. C#’s default is pass-by-value, which takes in-mode
parameters. Sebesta explains that pass-by-value usually passes a copy to the method. It is
typically fast for scalars, but it also uses more storage since it is working with a copy (Sebesta
401). Pass-by-result, which uses out-mode parameters, has the same advantages and
disadvantages of pass-by-value, but with the extra problem of possible parameter collision.
Page | 12
Meg Yahl
CSC 415 Term Paper
11/20/2012
(Sebesta 401). C# requires the out modifier in the formal parameter list when using out-mode
parameters.
There are two semantic models for inout-mode parameters. Pass-by-value-result is
basically a combination of pass-by-value and pass-by-result, with the disadvantages of each.
Pass-by-value-result requires more storage and time, and there is a greater risk of variable mixups via assignment order. Pass-by-reference also handles inout-mode parameters. C# requires the
keyword ref before both the formal and actual parameters. The difference between pass-byvalue-result and pass-by-reference is that the latter “transmits an access path, usually just an
address, to the called subprogram” (Sebesta 403). While pass-by-reference is more efficient with
time and space, it has slower formal parameter access. It can also create aliases, which can really
hurt readability and reliability. It is interesting to note that “C# allows methods to accept a
variable number of parameters, as long as they are of the same type.” (Sebesta 393)
Type checking
Type checking is very important in a programming language. It greatly impacts
reliability. “Without type checking, small typographical errors can lead to program errors that
may be difficult to diagnose because they are not detected by the compiler or the run-time
system” (Sebesta 408). Also, mismatched types can yield unexpected results or errors. In passby-reference, upgrading a float to a double is of no concern, but downgrading the double back to
a float can cause an overflow error. “To avoid this problem, C# requires the type of a ref actual
parameter to match exactly the type of its corresponding formal parameter” (Sebesta 410).
Stack-Dynamic local variable allocation
Local stack-dynamic variables are “bound to storage when the subprogram begins
execution and unbound from storage when that execution terminates” (Sebesta 398). In C#,
Page | 13
Meg Yahl
CSC 415 Term Paper
11/20/2012
methods “have only stack-dynamic local variables” (Sebesta 399). Stack-dynamic variables have
both advantages and disadvantages. They are a must-have for recursive subprograms, and “the
storage for local variables in an active [method] can be shared with the local variables in all
inactive [methods]” (Sebesta 398). They are also more flexible. However, stack-dynamic
variables have a higher time cost and must be accessed indirectly. Additionally, “methods with
all stack-dynamic local variables can’t retain data values of local variables between calls”
(Sebesta 398).
Nested Methods
C# does not allow nested methods.
Methods As Parameters (C# Delegates)
Typically, passing methods as parameters is handled by passing pointers to the method
instead of the actual method itself. “In C#, the power and flexibility of method pointers is
increased by making them objects. These are called delegates, because instead of calling a
method, a program delegates that action to a delegate” (Sebesta 420). Essentially, a delegate is
like a messenger. The program invokes a delegate, which in turn invokes the desired method.
This provides a level of abstraction from the caller and the target method. “An instantiation of a
delegate holds the name of a method with the delegate’s protocol that it is able to call. The
syntax of a declaration of a delegate is the same as that of a method declaration, except that the
reserved word delegate is inserted just before the return type” (Sebesta 420). Delegates can call
instance methods, “in which case the delegate must store a reference to the method” (Sebesta
421). Additionally, delegates “are also used to implement closures” (Sebesta 421).
To illustrate some of the delegate class’s properties, let the delegate class be thought of as
a telemarketer call center. Each telemarketer (the delegate) has a list of phone numbers (the
Page | 14
Meg Yahl
CSC 415 Term Paper
11/20/2012
target methods). This list can contain zero (null) or more phone numbers. The telemarketer must
go through list in order (a multicast delegate) before they can leave work. At the end of a long
day, only the last number called really stands out in the telemarketer’s memory. The call center
can also have automated dialers with prerecorded messages (generic delegates). In the case of a
technical support center, the employees (delegates) are presented with a particular situation that
has occurred (event), and they must resolve the situation accordingly (event handling).
Overloaded Methods
And overloaded method is a method “that has the same name as another [method] in the
same referencing environment” (Sebesta 397). Overloaded methods have to have some
distinction from each other or the program cannot tell which method to use. This ambiguity is
avoided by varying the number, order, or type of parameters. In some languages, having different
return types can distinguish the methods, but this does not “help in C# because it allows mixedmode expressions” (Sebesta 422). The meaning is determined by the actual parameter list when
the method is called.
Generic Methods
A generic method is a method “whose computation can be done on data of different types
in different calls” (Sebesta 397). The idea is that methods with similar functionality should not
have to be written multiple times for various data types. In some circles, this concept is known as
DRY, or “don’t repeat yourself.” C# generic methods are unique in that “the actual type
parameters in a call can be omitted if the compiler can infer the unspecified type.” (Sebesta 427)
Abstract Data Types and Encapsulation Constructs
Page | 15
Meg Yahl
CSC 415 Term Paper
11/20/2012
According to Sebesta, “an abstract data type is an enclosure that includes only the data
representation of one specific data type and the subprograms that provide the operations for that
type” (Sebesta 475). An object is an instantiation of an abstract data type. Abstraction is key to
readability because it hides code that is not necessary to the understanding of the program. Only
subclasses of abstract classes can be instantiated, not the parent class. “Abstract classes are able
to define abstract members. Abstract members are like virtual members, except they don’t
provide a default implementation. That implementation must be provided by the subclass, unless
that subclass is also declared abstract” (Albahari 80).
Another abstract data type is an interface. Interfaces do not have to be declared abstract
since they are always implicitly abstract, as are their members. C# interfaces are similar to Ada
package specifications in that they specify their members, but they do not implement them. The
class or struct that inherits the interface is responsible for implementing every member specified
in the interface. These “interface members are always implicitly public and cannot declare an
access modifier, [so] implementing an interface means providing a public implementation for all
its members” (Albahari 92). It is interesting to note that structs cannot inherit from classes, but
they can implement interfaces. Additionally, classes can only inherit from one class, but they can
implement more than one interface. Albahari states that objects can be implicitly casted to any
interface that they implements (Albahari 92).
Support for Object-oriented Programming
Objected-orientation is built on three main pillars: encapsulation, inheritance, and
polymorphism. C# was essentially built with object-orientation in mind. C# has a few unique
object-oriented features: a unified type system; classes and interfaces; and properties, methods,
and events. Most of these features have been discussed earlier in this report. As a brief recap of
Page | 16
Meg Yahl
CSC 415 Term Paper
11/20/2012
these points, some definitions follow. A unified type system means that “all types ultimately
share a common base type” (Albahari 1). Classes are a type in the object-oriented paradigm, and
“an interface is like a class except it is only a definition for a type, not an implementation”
(Albahari 1). Many languages do not support multiple inheritance, but C# can by implementing
multiple interfaces. Methods were also touched on earlier, but will now be revised somewhat.
Earlier, it was stated that methods were a general name for all subprograms, or functions.
Really, they are “only one kind of function member, which also includes properties and events
(there are others, too). Properties are function members that encapsulate a piece of an object’s
state, such as a button’s color or a label’s text. Events are function members that simplify acting
on object state changes” (Albahari 2).
Concurrency
According to Sebesta, “Two of the primary facilities that languages that support
subprogram-level concurrency must provide are mutually exclusive access to shared data
structures
(competition
synchronization)
and
cooperation
among
tasks
(cooperation
synchronization)” (Sebesta 623).
C# handles competition synchronization naturally by using monitors. Because of this,
“cooperation synchronization ... must be provided with some form of semaphores” (Sebesta
624). Semaphores are data structures “consisting of an integer and a task description queue.
Semaphores can be used to provide both competition and cooperation synchronization among
concurrent tasks” (Sebesta 624). However, if semaphores are used incorrectly, they can result in
“errors that cannot be detected by the compiler, linker, or run-time system” (Sebesta 624). These
potential undetected errors can severely impact reliability.
Page | 17
Meg Yahl
CSC 415 Term Paper
11/20/2012
According to Sebesta, “C#’s support for concurrency is based on that of Java but is
slightly more sophisticated” (Sebesta 624). He explains the many abilities of threads:
Any method can be run in a thread. Both actor and server threads are supported. All
threads are controlled through associated delegates. Server threads can be synchronously
called with Invoke or asynchronously called with BeginInvoke. A callback method
address can be sent to the called thread. Three kinds of thread synchronization are
supported with the Interlocked class, which provides atomic increment and decrement
operations, the Monitor class, and the lock statement (Sebesta 624-625).
Additionally, “all .NET languages have the use of the generic concurrent data structures for
stacks, queues, and bags, for which competition synchronization is implicit” (Sebesta 625).
Exception Handling and Event Handling
Exceptions
Like many other languages, C# has a built-in exception class: System.Exception.
Exception handling utilizes the try, catch, and finally blocks. According to Albahari, “The try
block must be followed by a catch block, a finally block, or both. The catch block executes when
an error occurs in the try block. The finally block executes after execution leaves the try block
(or if present, the catch block), to perform cleanup code, whether or not an error occurred”
(Albahari 134). Catch blocks are used to handle the exception or log the issue. If an exception is
predictable and can be handled in basic code without using the System.Exception class, it should
be done that way. This is because “exceptions are relatively expensive to handle, taking hundreds
of clock cycles” (Albahari 136).
Since the purpose of catch blocks is to handle the exception, it must be able to tell what
kind of exception was thrown. This is specified by the programmer, and it usually a specific
Page | 18
Meg Yahl
CSC 415 Term Paper
11/20/2012
exception. The entire System.Exception class can be caught, but there are relatively few cases
when this is necessary. Albahari gives a few examples of these cases, including the potential
recovery of the program regardless of the specific exception type, planning to rethrow the
exception after logging it, or the error handler being a last resort prior to termination of the
program (Albahari 136). It is also possible to “handle multiple exception types with multiple
catch clauses” (Albahari 136).
Events
“An event is a notification that something has occurred that requires special processing.
Events are often created by user interactions with a program through a graphical user interface”
(Sebesta 665). Handling these events is fairly straightforward in C#. Like all other .NET
languages, “event handlers are registered by creating an EventHandler object and assigning it to
the predefined delegate associated with the GUI object that can raise the event” (Sebesta 665).
After an event is detected, the code in the corresponding EventHandler is executed.
Evaluation of C# Language
The following evaluation is the author’s own personal opinion regarding the readability,
writability, and reliability of C#.
Readability
Personally, I believe C# is readable without much trouble. Most variable types, methods,
and properties feel pretty intuitive. int means integer, float means floating point, bool means
Boolean, and so on. If someone has had exposure to object-oriented programming, it should be
easy to understand that Console.WriteLine(“Hello World!”); means write “Hello World!” in the
console window. Keeping code uncluttered by abstracting common elements also makes C# easy
Page | 19
Meg Yahl
CSC 415 Term Paper
11/20/2012
to read. User-defined structs and enumerations let programmers clearly name what may
otherwise be confusing.
On the other hand, some of C#’s features can make readability more difficult as well.
There are many ways to do different things in C#. While that is great for writability, it is not
necessarily so good for readability. Aliasing is another hit to readability. Having too many names
for the same thing can be really confusing. Overall, readability is fairly good.
Writability
As mentioned above, having many different ways to accomplish a particular task is very
convenient for writability. While not a direct language feature, Microsoft’s Visual Studio IDE
makes writing code a breeze with Intellisense. C# is very strict with its syntax, which can hinder
beginners initially. Overall, writability can be a little difficult for beginners, but it can soon be
overcome.
Reliability
C# has many features that improve reliability. It has very strict type-checking, and
implicit casting is only done when there is guaranteed to be no loss of precision. C#’s built-in
Exception class also makes code much more reliable, provided it is utilized properly. Aliases can
make code less reliable, as can semaphores when used incorrectly. Any use of unsafe code has to
be explicitly stated in the code and enabled in the complier. Overall, C# is a very reliable
language.
Page | 20
Meg Yahl
CSC 415 Term Paper
11/20/2012
Appendix
Item 1: “GOTO”
http://xkcd.com/292/
Page | 21
Meg Yahl
CSC 415 Term Paper
11/20/2012
Bibliography
Afana, Nadeem. Primitive, Reference, and Value Types. 12 September 2005. 30 September 2012
<http://www.codeproject.com/Articles/11212/Primitive-Reference-and-Value-Types>.
Albahari, Joseph, and Ben Albahari. C# 4.0 in a Nutshell. 4th Edition. Sebastopol: O'Reilly
Media, Inc., 2010.
Clark, Dan. "Overview of Object-Oriented Programming." Clark, Dan. Beginning C# ObjectOriented Programming. Apress, 2011. 6.
Hejlsberg, Anders. The A-Z of Programming Languages: C# Naomi Hamilton. 1 October 2008.
Hejlsberg, Anders. The A-Z of Programming Languages: C# Naomi Hamilton. 1 October 2008.
Lippert, Eric. Not everything derives from object. 6 August 2009. 10 November 2012
<http://blogs.msdn.com/b/ericlippert/archive/2009/08/06/not-everything-derives-fromobject.aspx>.
Microsoft Corporation. C# Operators (C# Reference). 2012. 30 September 2012
<http://msdn.microsoft.com/en-us/library/6a71f45d.aspx>.
—. Enumeration Types (C# Programming Guide). 2012. 30 9 2012
<http://msdn.microsoft.com/en-us/library/cc138362.aspx>.
—. for (C# Reference). 2012. 30 September 2012 <http://msdn.microsoft.com/enus/library/ch45axte.aspx>.
—. foreach, in (C# Reference). 2012. 30 September 2012 <http://msdn.microsoft.com/enus/library/ttw7t8t6.aspx>.
—. if-else (C# Reference). 2012. 30 September 2012 <http://msdn.microsoft.com/enus/library/5011f09h.aspx>.
Page | 22
Meg Yahl
CSC 415 Term Paper
11/20/2012
—. Reference Types (C# Reference). 2012. 30 September 2012 <http://msdn.microsoft.com/enus/library/490f96s2.aspx>.
—. Struct (C# Reference). 2012. 30 September 2012 <http://msdn.microsoft.com/enus/library/ah19swz4.aspx>.
—. switch (C# Reference). 2012. 30 September 2012 <http://msdn.microsoft.com/enus/library/06tc147t.aspx>.
—. Types (C# Programming Guide). 2012. 30 September 2012 <http://msdn.microsoft.com/enus/library/ms173104.aspx>.
—. Value Types (C# Reference). 30 September 2012 <http://msdn.microsoft.com/enus/library/s1ax56ch.aspx>.
Sebesta, Robert W. Concepts of Programming Languages. 10th Edition. New York: AddisonWesley, 2012.
Vrajitoru, Dana. Name, Scope, Binding. 2012. 30 September 2012
<http://www.cs.iusb.edu/~danav/teach/c311/c311_3_scope.html>.
Page | 23