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#).
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 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
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).
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 that would otherwise require complicated reflection code. Dynamic binding is also useful when interoperating with dynamic languages and COM components” (Albahari 5).
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.
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 explanation, Lippert concludes that “every non-pointer type in C# is convertible to an object” (Lippert).
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 programmers are able to give clear names and structure to what may otherwise be difficult to understand.
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).
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 ‘template’ that contains ‘placeholder’ types. Generics, when compared to inheritance, can increase type safety and reduce casting and boxing” (Albahari 101).
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 performance-critical hotspots” (Albahari 170).
Expressions and Assignment Statements
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 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 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.
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.
StatementLevel 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.
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 case-constant 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 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 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.
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, do-while, 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 (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).
In C#, subprograms in general are referred to as methods. Methods can have any type, including user-defined types and void.
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. (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 mix-ups 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-by-value-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 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 pass-by-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#, 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).
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 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).
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 mixed-mode expressions” (Sebesta 422). The meaning is determined by the actual parameter list when the method is called.
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
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 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).
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.
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
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 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).
“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 EventHandlerobject 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#.
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 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.
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.
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.
Item 1: “GOTO” http://xkcd.com/292/
Afana, Nadeem. Primitive, Reference, and Value Types. 12 September 2005. 30 September 2012 .
Albahari, Joseph, and Ben Albahari. C# 4.0 in a Nutshell. 4th Edition. Sebastopol: O'Reilly Media, Inc., 2010.