The Bonus Site for
C# 2008
For Dummies
csharp102.info
To help you evaluate the book, here's the Table of Contents with annotations:
This short part of the book lets you clear your throat and get a basic sense of what's involved in using Visual Studio to write a C# program. Not much of a program, but ... hey, it's a start.
Get a feel for working with C# in Visual Studio by creating a simple app that says, "Hello."
Programming in most any programming language involves writing straightforward code statements that add and subtract numbers, manipulate character strings, and put bits of data into variables, including collective variables that can hold multiple bits of data. Such code also repeats code in loops and makes decisions, carrying out one set of statements if married, another set if divorced. Pay close attention to these fundamental C# skills. They're the heart of the language, the bread-and-butter stuff you do day in, day out as a programmer.
Start using variables to store bits of data. Variables come in a wide variety of kinds and sizes: integers, long integers, short integers, bytes, strings, characters, dates, Students, BankAccounts -- the sky is the limit.
Having variables isn't enough. You also need to be able to do things with them: add them, divide them, grill and sauté them -- using operators that stand for those actions.
It gets boring just telling the computer "Do this, do that, do that, do that" (that's what a program is: a set of instructions), one command after another in a straight line. Often you need to make decisions:
if x is 2 then buy a fat pig, else jiggety jig
Besides making choices with C#'s 'if,' 'else,' and 'switch' statements. Or you need to do the same basic thing (possibly with variations) over and over. C#'s loops, such as 'for,' 'foreach,' and 'while' statements take care of that. Taken together, these commands let you control the flow of your program.
Suppose you're a teacher averaging a student's grades. You need a variable that can hold not one, but many values -- that's an array, or a list. You can loop through the list adding up the values, then divide the sum by the number of values. Or you need a list that can work in special ways: a queue that works like the line to order your Burger Whop; or a stack that works first in-last out and last in-first out; or a list that works like a mathematical set. C# has 'em all.
Lots of data comes in the form of letters and words. So C# provides the char and string data types and gives you lots of operations you can do on them.
Back to TopC# is said to be an object-oriented programming (OOP) language. Object-orientation is really a style of coding, not a language feature that you can turn on and off. Likewise, it's quite possible to write code using objects without really venturing into object-oriented programming. Hence the distinction between Part III and Part IV. In order to write object-oriented programs, you need objects. Part III shows you how to build objects. Part IV shows how to use them in OOP programs.
Although C# gives you a ton of built-in data types, such as integers, chars, strings, and dates, you'll often need to create variables for custom kinds of data. So C# lets you define the structure and other characteristics of your own data types and give them custom actions. This is done with the 'class' keyword.
What can a custom class data type do? You specify actions that can be performed on that type -- for instance, enrolling a Student in a course, or depositing some money in a BankAccount. These actions are called 'methods.'
Consider a data type for BankAccounts. Each bank account has its own current balance. But you might also want to track how many accounts are out there. The 'static' keyword lets you store a value once (for example, how many accounts exist ), in a way that lets all bank account objects share that value. Meanwhile, without the static keyword, you can specify things that belong to individual bank accounts, such as each one's balance. The 'this' keyword gives you a way to refer to the current object: this one right here, not that one over there. With 'this' you can work with BankAccount A's balance as opposed to BankAccount B's balance.
Back to TopNow that you know what objects are, you can start OOPing the OOP in Part IV, which covers encapsulation, inheritance, polymorphism, and other OOP techniques.
In C#, every chunk of data -- from the integer 5 to the name of your cat to your personal savings account -- is an object. Treating things as objects helps structure your code and work with abstractions, such as BankAccounts or Students. You can deposit $50 to a particular BankAccount object without worrying about the details. Because the BankAccount class -- or data type -- is equipped with a Deposit operation and thus knows how to handle the detailed mechanics of making a deposit. All the user of a BankAccount object needs to know is which BankAccount object she's using and the fact that it has a Deposit action.
Some of the data stored in, say, a BankAccount object, is public -- anybody (with reasonable credentials, such as being the account owner or being a bank employee) can view the account's balance. But some of the account's data isn't intended to be public. Some is public, some is private, and some is in between. C# lets you hang a label on the bits of data stored in an object to keep unauthorized users from accessing and modifying that data. Not only does this keep out the unauthorized, it also keeps users -- including you -- from making dumb mistakes that can screw up the integrity of the data.
You may have noticed that a SavingsAccount is a kind of BankAccount. C# lets you show that relationship through inheritance. The BankAccount class can define most of the account's characteristics and behavior. And the SavingsAccount class can just define the differences specific to savings. The BankAccount class is often called the base class (or superclass, or ancestor class), while the SavingsAccount is called a subclass (or descendant class). Not only does this kind of inheritance let you show relationships, it reduces the amount of code you must write, and it reduces the complexity of your code -- which helps reduce errors.
Objects like BankAccounts and SavingsAccounts have some common features. For example, you can deposit to each, or withdraw from each. Having a known set of common features, such as common properties (a balance) and common actions (Deposit, Withdraw), allows you to substitute a subclass, such as SavingsAccount, for a base class, such as BankAccount. This lets you do useful things like create an array of accounts. Then you can loop through the array calling each account's GetBalance action or Deposit action, without regard for what kind of account each is. This ability is called by the absurd Greek name "polymorphism," which means something like "many shapes."
When two objects have the same set of properties and operations, they're said to have the same interface. Each object will thus have a predictable set of methods you can call (see Chapters 8 and 9 above). One of the bedrock abilities that makes object-oriented programming possible is the C# interface data type. An interface definition makes for highly general code because it simply specifies the names of the properties and methods that must be provided by any object that "implements" the interface. Thus an interface might specify a Read operation. Any class that implements that interface must provide a Read method that matches the interface's Read definition. But different implementing classes might implement Read differently. Polymorphism doesn't care about exactly what a Read method does. It just cares that there IS a Read method. Thus, for example, you might write one class that provides a test implementation for Read and another class that provides a real working version of Read.
Back to TopC# is not a one-trick pony. Each new version of C# adds new tricks. For C# 3.0, the new stuff is all about manipulating data in a streamlined, slimmed-down way with Language Integrated Query (LINQ). If you've encountered database programming at all, you'll find that LINQ lets you do similar kinds of queries on more kinds of data. Besides querying databases, you can query data stored in Extensible Markup Language (XML) or in plain old C# collections. I don't cover the database or XML query stuff, but after grasping LINQ to Objects (in collections), you should be able to move on to LINQ to SQL and LINQ to XML later.
C# lets you define a 'delegate' object through which you can pass around methods as if they were objects. This lets you do tricky things like callbacks and do-to-each operations. Suppose you have a list of Students and you want to do the same thing to each student. The list knows nothing about your custom operation. But a delegate lets you specify the details of the operation and then pass those details into the list. The list simply applies your custom code to each object. Or suppose you need to start a parallel operation (using a 'thread,' which I don't cover in the book), but you want to get an update from time to time while that parallel operation is running. A real example of this kind of 'callback' technique is the progress bars you see in many dialog boxes -- a green or blue bar that gradually fills up as a lengthy operation continues. You start the lengthy operation, passing in a piece of code (a method) via a doorway defined by a delegate object. Periodically, the lengthy operation 'calls back' to report its progress. Each time it calls back, the parent code can increment the progress bar a bit.
C# has had delegate types (see Chapter 15 above) all along. In C# 2.0 back in 2005, the language also offered a shortcut way to provide the code to a delegate: something called an 'anonymous method.' Anonymous methods were a great improvement over the creaky mechanics of setting up a delegate. But C# 3.0, new in 2008, improves even on anonymous methods. A 'lambda expression' (don't freak at the weird name) is a very compact way to define a small piece of code that you can pass to a delegate. For example, the Find method of arrays takes a special kind of delegate object called a 'predicate.' A predicate is simply a condition used for comparison: x == 5, say. You can pass a lambda expression to specify the predicate that you want to look for in the array: for example,
x => x == 5
This expression is used by Find to compare each number in the array to 5. Find returns the first value in the array that matches the expression. The heart of a lambda expression is the lambda operator, =>. Lambda expressions can do even more. Instead of a Boolean true/false condition -- a predicate -- a lambda expression can specify actions to carry out. For instance, the array's DoToEach method can take a lambda expression such as this:
p =>
Console.WriteLine(p)
Whatever p is for each array element gets printed out to the console. Not only do lambda expressions simplify working with delegates, they're also the basis for the 'query expressions' in Chapter 17.
The conventional way to carry out many tasks involves things like if statements and loops. For example, to sum up the numbers in an array of 10,000 integers, you'd loop through the array and add each new element to the running sum. Or to search for the first element in the array that meets some criterion, you'd loop through the array comparing each element with the criterion. That's fine, but look at what you're actually doing with such code. You want task A done. You specify in excruciating detail, via your code, exactly how to carry out task A. But suppose you could just tell the computer, Do Task A, and let it figure out how to give you the results you're looking for. It's kind of a 'Do What I Mean' button. Well, given an array of Students, say, you could specify -- via a 'query expression' -- that you want a list of the Students whose GPA exceeds 2.999:
from students where student = student.GPA
> 2.999 select student
The query expression lets you specify what you want. And C# can translate that into a set of steps that will produce the desired result. This kind of programming is called 'functional programming,' and it differs from the 'imperative programming' (Do This, Then This ...) that programmers have always done. C#'s query expressions are highly similar to the Structured Query Language (SQL) statements that database programmers have used for decades to extract information from databases. Thus they're familiar to many programmers already, and with C# you can use the same sorts of query expressions to work with data in a database, data in a C# array or list, or data in an Extensible Markup Language (XML) data file. This is powerful and liberating.
Back to TopEvery For Dummies book includes a Part of Tens - which contains lists of the top ten thises or thats. This book includes ten of the most common errors you'll encounter when you compile your C# programs.
Your code won't compile without errors. That could never happen in my code! Sure it will. This chapter explains ten of the most common compile errors and how to fix them.
Most For Dummies books throw in a few bonus items that don't appear in the printed book. For this one, I've provided seven Bonus Chapters (and more code examples). The Bonus Chapters are available on this Web site, on the Bonus Chapters page.
Programs can get really large -- millions of lines, even -- so it helps if you can divide them up into chunks of code that are easier to understand than the whole undivided program. One way to do that is by dividing the program up into 'class libraries' -- separate chunks of code that other chunks can call upon to do specialized work. Another kind of division, or "chunking," is to wrap code in 'namespaces.' A class or method named 'foo,' in one namespace, for instance, doesn't interfere or "collide" with something named 'foo' in another namespace.
Things do go wrong in programs as they run. The file you need isn't on the disk. You fail to connect to the remote database. A variable has an unexpected value. When things go wrong at run-time, C# code 'throws' an 'exception.' Exceptions are objects, like everything else in C#, and the C# common language run-time engine, the CLR, manages bubbling these objects up from the method where the Ferrari hit the tree to the method that called that method, and then the method that called that one, and the caller of that, etc. The idea is that the object is looking for a 'handler' -- a piece of code that can do something useful with the exception, even if it's just informing the user that "we're doomed" and letting the program go belly-up. It's a graceful, flexible way to manage inevitable errors in C#.
Back to TopMany programs need to do some input/output (I/O). Write a file to disk as a permanent copy. Read a data file received over the Web in order to process the data. C# does I/O via easy-to-use Stream objects.
C#'s classes aren't the only way to package related sets of data into objects that can be manipulated as objects. C# also supplies the structure, or 'struct,' data type. Interestingly, the struct is what makes C# all objects, all the time. Because the integers and chars and floating-point numbers used so widely are, in C#, actually implemented as structs (with handy aliases like 'int,' 'float,' and 'double') and official, behind-the-scenes names like 'Int32,' 'Char,' and 'Double,' there's no double standard in C#, as there is in some other languages, such as Java. It's turtles -- 'er, objects -- all the way down.
While it's possible to program with C# at the Windows command line, most people prefer a friendlier environment, one that provides amenities like specialized editors, toolboxes, multiple working windows, and tons of commands that simplify doing difficult things -- thereby reducing errors in the code. Microsoft's Visual Studio isn't the only such "integrated development environment" (or IDE), but it's the one most commonly used, the most up-to-date, and the most powerful. (Alternatives include SharpDevelop, about which I'll soon have more to say on this Web site.) Visual Studio comes in editions that range from the ultimate high-powered team-oriented Team System down to the Professional, Standard and Express editions. Most developers pay good money for the Professional Edition, but hobbyists and newbies can freely download the Express edition: Visual C# 2008 Express. It's a free download from Microsoft, though of course it has some limitations. This chapter gives you a pretty solid tour of Visual Studio that will have you up and coding pronto.
Sometimes you need a List of integers. Other times you need a List of Students. In the bad old days, not so long ago, you often had to build such specialized type-specific data structures yourself -- or use the general but cumbersome and rather error-prone ArrayList, in which everything is of type Object, not int, or Student, or whatever you actually need. Putting your custom objects into such a list is easy because ALL C# data types are descended, through OOP inheritance, from type Object, the root of the entire type system. You can store any type in a variable of type Object. But taking things out is harder, requiring a conversion, or 'cast,' from Object to the type you expect to be stashed in the Object. Such a list even lets you store Apples and Oranges in the same list. But then how do you know which type of fruit to cast each object to as you take them out? Since 2005, C# has provided "generic" data types. A generic list, such as List<Student>, can store only Student objects. But it's easy to write a different list that can store only Apples: List<Apple>. And it's not just generic lists. C# has generic queues, stacks, linked lists, sets, and other generic collection types, and it also lets you write your own arbitrary generic classes. Even more, you can write generic methods, even in nongeneric classes, generic interfaces, and generic delegates. This is very versatile and powerful, and it's not very hard to do. This chapter shows you how.
Collections are handy, but this chapter adds to the collections story by discussing the various ways you can iterate (traverse, walk or loop through) a collection. I show you how to write your own linked list class, then I take you through indexers and the newest kid on the iteration block, the 'iterator block.'
And if that smorgasbord leaves you still hungry, this Web site has a slew of additional articles on C#, all aimed at the For Dummies reader.
Back to Top