C# 3.0 Unleashed: With the .NET Framework 3.5

Introduction

C# 3.0 Unleashed: with the .NET Framework 3.5C# 3.0 Unleashed: With the .NET Framework 3.5 is a book that thoroughly covers the C# programming language.  It has 5 chapters on data access technologies and continues to show you how to use those data technologies throughout the rest of the book.  C# 3.0 Unleashed shows you how to get started with several UI technologies, including Windows Forms, ASP.NET, ASP.NET AJAX, and Silverlight.  There are also more advanced chapters for important subjects, such as architecture, design, security, and CLR concepts.  Peppered with advice from an experienced software engineer, you'll receive a wealth of knowledge you can apply in your own real-life software development scenarios.

Free Sample Chapters

On CoDe Magazine: Chapter 1: Introducing the .NET Platform

Additional Details

Amazon.com

InformIT/Safari

Errata

C# 3.0 Unleashed has some layout errors and typos that you should be aware of. For any questions, error reports, or feedback; please use the Contact Form.

Chapter 1

Page 10

Replace figure 1.2 with the following:

Managed Compilation

Page 16, Para 5

Change "Table 1.2" to "Table 1.3".

Chapter 2

Page 44, Code After Para 1

Replace with the following:

         string logFileName2 = "c:\\Projects\\MyGreatApp\\error.log";

Page 45, Code After Last Paragraph

Replace with the following:

        static void Main(string[] args)
        {
            Console.WriteLine("Your option
                is: {0}", args[0]);

            Console.ReadKey();
        }

Chapter 3

Page 56, Last Line of Code on Page

Replace with:

 isEven = (oddMask & someByte) == 0; // isEven is false

Chapter 4

Page 89, 90

Figures 4.7, 4.8, and 4.9 are out of order.

Figure 4.8 should be Figure 4.7.
Figure 4.9 should be Figure 4.8.
Figure 4.7 should be Figure 4.9.

Page 93, Para 2, Sentence 3

Change "Chapter 3, Writing C# Expressions and Statements" to "Chapter 2, Getting Started with C# and Visual Studio 2008, Table 2.6"

Page 94, Para 6, Sentence 1

Change "Chapter 3" to "Chapter 2"

Page 100, Table 4.2

D (short date), T (short time), F (short time), G (short time), M (left), S, U (first/sortable), Y (left) should be lower case.

Page 101, Table 4.3

All D, S, Y, H ( regular hour), M (minutes) should be lower case.

Chapter 5

Page 106, Para 3, Sentence 2

Change "Chapter 1, Introducing the .NET Platform" to "Chapter 2, Getting Started with C# and Visual Studio 2008"

Page 106, Code After Para 3

Replace with the following:

            string str2 = "string 2";

            string formatString = "{0,15}";

            strResult = string.Format(formatString, str2);

            Console.WriteLine("string.Format({0},{1}) = [{2}]\n",
              formatString, str2, strResult);

With the following output:

string.Format({0,15}, string 2) = [       string 2]

Page 107, Output After Para 3

Replace with the following:

string.Format({0,-15}, string 2) = [string 2      ]

Page 114, Para 8 (last output example)

Replace with:

filePath.LastIndexOf(@"\"): 43

Page 114, Para 9, Sentence 1

Replace sentence with:

This example was another opportunity to show you the verbatim string literal symbol, shown in @"c:\Windows\Microsoft.NET\Framework\v3.5.x.x\csc.exe".

Page 115, Output After Para 6

Replace with:

str1.PadLeft(15): [       string 1]

Page 116, Para 7, Sentence 2

Replace "nonwhitespace" with "  nonwhitespace" (leaving two spaces to the left of the word)

Page 116, Para 8, Sentence 2

Replace "nonwhitespace  " with "nonwhitespace  " (leaving two spaces to the right of the word)

Chapter 6

Page 135, Code Before First Para

Replace with the following:

            int dimOneSize = 2;
            int dimTwoSize = 2;

            for (int i = 0; i < dimOneSize; i++)
            {
                for (int j = 0; j < dimTwoSize; j++)
                {
                    Console.WriteLine(
                        "exclusiveOr[{0}, {1}]: {2}",
                        i, j, exclusiveOr[i, j]);
                }
            }

Page Code at Bottom of Page 137, Continuing on Page 138

Replace with:

             for (int i = exclusiveOr.GetLowerBound(0); 
                     i <= exclusiveOr.GetUpperBound(0); i++)
            {
                for (int j = exclusiveOr.GetLowerBound(1); 
                         j <= exclusiveOr.GetUpperBound(1); j++)
                {
                    Console.WriteLine(
                        "exclusiveOr[{0}, {1}]: {2}",
                        i, j, exclusiveOr[i, j]);
                }
            }

Page 138, Code After Para 3

Replace with the following:

Array kelvinTemperature = Array.CreateInstance(
    typeof(double), 
    new int[] { 100 }, 
    new int[] { -100 });

Page 143, Para 8

Change "GetObject" to "ToObject".

Chapter 7

Page 148, Para 1, Sentence 2

Replace with:

The Mulitiply method multiplies a couple numbers and then returns them.

Chapter 8

None

Chapter 9

Page 198, Para 1, Sentence 1

Append " for value types" to the end of the sentence.

Chapter 10

None

Chapter 11

None

Chapter 12

Page 261, Para 1, Sentence 1

Replace with:

"Listing 12.3 contains the DelegatesAndEvents class. In the Main method of DelegatesAndEvents, you'll see references to MenuItem (Listing 12.2), SiteManager (Listing 12.4), and Menu (Listing 12.5).

Chapter 13

None

Chapter 14

Page 296, Listing 14.3

Change:

FinanceCompany finco = new FinanceCompany();

To:

IBroker finco = new FinanceCompany();

Chapter 15

Page 324, 325

Replace the entire section titled "Inheritance and Order of Instantiation with this:

*** Begin Replacement Text ***

Inheritance and Order of Instantiation

When instantiating classes in an inheritance chain, you need a deterministic way to know which classes instantiate first. This section clarifies what you need to know about the order of invocation for constructors and some tricky scenarios you'll want to know about.

There are three scenarios I’ll walk through to demonstrate order of instantiation with inheritance: default constructors, parameterized constructors, and controlling which base class constructor is called. The first scenario below demonstrates the sequence of instantiation among classes; Base class constructors execute before derived class constructors:

public class Base1
{
    public Base1()
    {
        Console.WriteLine("Called Base1().");
    }
}

public class Derived1 : Base1
{
    public Derived1()
    {
        Console.WriteLine("Called Derived1().");
    }
}

public class InitializationSequence
{
    static void Main()
    {
        Derived1 der1 = new Derived1();
        Console.WriteLine();

        Console.ReadLine();
    }
}

And here’s the output:

Called Base1().
Called Derived1().

To understand what is happening above, start with the Main method, where it instantiates Derived1. During instantiation, the default constructor for the class at the top of the inheritance hierarchy, Base1, runs first. Then each constructor from the top down executes. You can see in the output above that the Base1 constructor executed first and then the Derived1 constructor executed. This sequence ensures that your base class is properly instantiated before derived classes that might depend on base class state.

Next, you’ll see how parameterized constructors behave. This part is a little tricky because many developers initially think that a derived constructor call will initiate a call on the base class constructor with the same signature, but that isn’t true. The real behavior is that the default constructor in the base class is called, as shown below:

public class Base2
{
	public Base2()
	{
		Console.WriteLine("Called Base2().");
	}

	public Base2(string someString)
	{
		Console.WriteLine("Called Base2(string
            someString).");
	}
}

public class Derived2 : Base2
{
	public Derived2() : this ("some
            string")
	{
		Console.WriteLine("Called Derived2().");
	}

	public Derived2(string someString)
	{
		Console.WriteLine("Called Derived2(string
            someString).");
	}
}
public class InitializationSequence
{
    static void Main()
    {
        Derived2 der2 = new Derived2();
        Console.WriteLine();

        Console.ReadLine();
    }
}

And here’s the output:

Called Base2().
Called Derived2(string someString).
Called Derived2().

To follow how the code above works, observe that the default constructor is used in Main to instantiate Derived2. Then, look at how the Derived2 default constructor uses the this keyword to invoke the Derived2(string) constructor. Since Base2 has a matching constructor overload with a string parameter, you might think that Base2(string) would be called, but that assumption would be incorrect. As shown in the output above, the default Base2 constructor is called instead. Then Derived2(string) runs, followed by the Derived2 default constructor.

If you’re having trouble wrapping your brain around this one, my recommendation is to set a break point in Main and step through the code. This is an important concept to remember because trying to instantiate a base class that doesn’t have a default constructor results in a compiler error. You can see this by commenting out the default constructor in Base2 and trying to compile the code.

Remember, C# will automatically generate a default constructor for you if no other constructors are defined. However, if there are other constructors defined and you haven’t defined a default constructor, C# will not generate the default constructor for you.

This leads us to the third scenario, where you might want to have some control over which base class constructor should be invoked. The following example uses the base keyword in the constructor signature to ensure that the parameterized base class constructor is called:

public class Base3
{
    public Base3(string someString)
    {
        Console.WriteLine("Called Base3(string
            someString).");
    }
}

public class Derived3 : Base3
{
    public Derived3()
        : this("some string")
    {
        Console.WriteLine("Called Derived3().");
    }

    // must call single parameter base
        constructor
    // because there isn't a default
        constructor
    // comment out call to base to see
        compile-time error.
    public Derived3(string someString)
        : base(someString)
    {
        Console.WriteLine("Called Derived3(string
            someString).");
    }
}

public class InitializationSequence
{
    static void Main()
    {
        Derived3 der3 = new Derived3();
        Console.WriteLine();

        Console.ReadLine();
    }
}

And here’s the output:

Called Base3(string someString).
Called Derived3(string someString).
Called Derived3().

The Base3 class above doesn’t have a default constructor, eliminating the default instantiation sequence as a possibility in this case. To fix this problem (avoid the compiler error), use the base keyword, with a parameter list that matches the signature of a base class constructor that you want to call instead. In the example above, Derived3(string) uses the base keyword to pass the someString constructor parameter as an argument to the Base3(string) constructor.

A classic example of when to use the base keyword is when creating a custom exception. In Chapter 11, “Error and Exception Handling”, Listing 11-6 and supporting discussion demonstrates how the TooManyItemsException constructor calls the base class constructor that takes a string parameter. For your convenience, here’s a snippet of the code:

public class TooManyItemsException : ApplicationException
{
    public TooManyItemsException() : base(@"
            **TooManyItemsException** You added too many items to this container. Try specifying
            a smaller number or increasing the container size.")
    {
    }
}

The default constructor above uses the base keyword to call the ApplicationException(string) constructor. This was a simple example of what you could do to ensure the proper base class constructor executes, but when designing your own class, you’ll want to add as many constructors as necessary and ensure they invoke base class constructors in a way that makes sense for your program.

This section concentrates on instance fields, but what about static fields? Static fields shouldn't be accessed within instance constructors because that could possibly create redundant code to execute every time a new instance is created or leave a class in an inconsistent state when subsequent static methods, if any, are invoked. A good rule of thumb is to keep static field initialization in static constructors and instance field initialization in instance constructors. The next section covers static constructors.

*** End Replacement Text ***

Chapter 16

None

Chapter 17

Page 376, Paragraph 1, Sentence 1

Replace with:

If you scan the definitions of each member in Listing 17.2, you'll see a commonality where the object type is represented by the T parameter.

Chapter 18

Page 398, Code after 2nd Paragraph

Replace with:

([parameter list]) => [expression];

Chapter 19

None.

Chapter 20

Page 448, Paragraph 4

Replace with:

To compile the code above, ensure the connection string appears on a single line and include a using directive for the System.Data.SqlClient namespace.

Chapter 21

Page 462, Paragraph 3, Sentence 1 and 3

Change XMLTextWriter to XmlTextWriter

Chapter 22

Page 476, Para 6, Sentence 2

Replace with:

In this chapter, we use the same Hospital database as used in Chapter 19, "Accessing Data with LINQ."

Page 477, Figure 22.2

Replace with:

Choosing Model Contents

Page 485, Steps 4.b and 4d

Remove both steps and renumber step 4c as 4b.

Page 485, Steps 6.b and 6d

Remove both steps and renumber step 6c as 6b.

Page 485, Step 9

Delete

Page 485, Step 10

Change CustomHospital.Target to CustomHospital.Store

Page 485, Step 8 and 10

Switch Steps - Step 8 becomes Step 10 and Step 10 becomes Step 8.

Page 485, Step 12

Change ?? to <empty string>.

Page 486, Code Snippet after Para 1

Replace with:

        using (var custHospital = new CustomHospitalContainer())
        {
            ObjectQuery<Doctor> doctorQuery =
                new ObjectQuery<Doctor>(
                    "select value Doc from CustomHospitalContainer.Doctors
                        as Doc",
                    custHospital);

            foreach (var doc in doctorQuery)
            {
                Console.WriteLine("Doctor: {0}", doc.Name);
            }
        }

Page 486, Para 2

Replace with:

This is the same type of query you saw in the previous section, except that the  ObjectQuery type parameter is Doctor, the ObjectContext is named CustomHospitalContainer, and the select statement accesses the fully qualified name CustomHospitalContainer.Doctors.

Pages 486, 487, and 488 Code Examples

Change CustomHospitalEntites to CustomHospitalContainer.

Page 488, Last Code Example

Change "90210" to "90210-0000".

Chapter 23

From Beta to RTM Changes to Make Throughout Chapter (including code)

Change WebDataService to DataService
Change IWebDataServiceConfiguration to IDataServiceConfiguration
Change SetResourceContainerAccessRule to SetEntitySetAccessRule
Change ResourceContainerRights to EntitySetRights
Change Microsoft.Data.WebClient to System.Data.Services.Client.dll

You'll notice that the XML ATOM  format from query results (when you view source in IE7) has changed, but the same instructions and concepts apply.

Page 492, Para 1

Change HospitalDataService.svx to HospitalDataService.svc.

Page 500, Para 6

Change the following command-line that starts with Webdatagen.exe to:

datasvcutil.exe /out:HospitalT ypes.cs /uri:http://localhost:5011/HospitalDataService.svc

Page 501 & 502, Updating Entities Section

Replace code example with this:

            var webCtx = new DataServiceContext(
                new Uri("http://localhost:5011/HospitalDataService.svc"));

            webCtx.MergeOption = MergeOption.AppendOnly;

            var docs = webCtx.Execute<HospitalStaff>(new Uri("HospitalStaff?$filter=Name eq 'No'&$top=1", UriKind.Relative));

            var drNo = docs.First();
            drNo.Position = "Nurse";

            webCtx.UpdateObject(drNo);

            webCtx.SaveChanges();

            docs = webCtx.CreateQuery<HospitalStaff>("/HospitalStaff");

            docs.ToList().ForEach(
                doc => Console.WriteLine(
                    "Update - Name: {0}, Position:
                        {1}",
                    doc.Name, doc.Position));

Page 502, Note on PreRelease Software Glitches

Delete note in its entirety because problem is resolved in RTM.

Page 502, Deleting Entities

Replace code example with this:

             var webCtx = new DataServiceContext(
                new Uri("http://localhost:5011/HospitalDataService.svc"));

            webCtx.MergeOption = MergeOption.AppendOnly;

            var docs = webCtx.Execute<HospitalStaff>(new Uri("HospitalStaff?$filter=Name eq 'No'&$top=1", UriKind.Relative));

            docs.ToList().ForEach(
                doc => webCtx.DeleteObject(doc));

            webCtx.SaveChanges();

            docs = webCtx.CreateQuery<HospitalStaff>("/HospitalStaff");

            docs.ToList().ForEach(
                doc => Console.WriteLine(
                    "Update - Name: {0}, Position:
                        {1}",
                    doc.Name, doc.Position));

Page 503, Para 2, Sentence 1

Replace with:

All the examples in this section called CreateQuery or Execute with parameters that match the data service URL parameters.

Page 503, Querying Entities with LINQ to DataService

Replace code example with:

            var hospital = new DataServiceContext(
                new Uri("http://localhost:5011/HospitalDataService.svc"));

            var docs =
                from doc in hospital.CreateQuery<HospitalStaff>("/HospitalStaff")
                where doc.Position == "Doctor"
                select doc;

            docs.ToList().ForEach(
                doc => Console.WriteLine(
                    "LINQ - Name: {0}", doc.Name));

Page 504, Para 1

Change the following command-line that starts with Webdatagen.exe to:

datasvcutil.exe /out:HospitalT ypes.cs /uri:http://localhost:5011/HospitalDataService.svc

Page 504, Para 2

Replace code after the paragraph with the following:

            var hospital = new HospitalEntities(
                new Uri("http://localhost:5011/HospitalDataService.svc"));

            var docs =
                from doc in hospital.HospitalStaff
                where doc.Position == "Doctor"
                select doc;

            docs.ToList().ForEach(
                doc => Console.WriteLine(
                    "LINQ - Name: {0}", doc.Name));

Chapter 24

None

Chapter 25

Page 524, Para 2, Sentence 2

Change VS2005 to VS2008.

Chapter 26

Page 552, Para 5, Sentence 1

Change Figure 26.2 to Figure 26.3.

Chapter 27

Page 605, Step 4

Change pr-defined to pre-defined.

Chapter 28

None

Chapter 29

Pages 651, First XAML Code that Starts at Bottom of 650

Replace with:

- <UserControl
xmlns:data
="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="Hospital.Page"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width
="400" Height="300">
- <Grid x:Name="LayoutRoot" Background="White">
- <StackPanel>
  <TextBlock
x:Name
="SilverlightMessage"
Text
="SilverlightControl"
MouseEnter
="SilverlightMessage_MouseEnter"
MouseLeave
="SilverlightMessage_MouseLeave" />
  <Button
x:Name
="LoadButton"
Content="Load"
Click="LoadButton_Click" />
  <data:DataGrid
x:Name
="HospitalDataGrid"
AutoGenerateColumns
="True"
Width
="400" Height="200" />
  </StackPanel>
  </Grid>
  </UserControl>

Chapter 30

None

Chapter 31

None

Chapter 32

Page 700, Para 4, First Sentence

Delete "first".

Page 701, First Para

Delete entire paragraph.

Chapter 33

None

Chapter 34

None

Chapter 35

None

Chapter 36

None

Chapter 37

None

Chapter 38

Page 807, Step 5, First Sentence

Change Iappointment to IAppointment.

Page 808, Para 1, Second Sentence

Change Iappointment to IAppointment.

Page 809, Para 1, Second Sentence

Change Iappointment to IAppointment

Page 811, Steps 5, 9, 14, and 19

Change StartState to TargetStateName

Chapter 39

Page 824, Running Code in a Thread with Less Code

Add the following code after the paragraph of this section:

            new Thread(
                () => Console.WriteLine(
                    "Hello from a single thread via
                        Lambda."))
            .Start();

Chapter 40

Page 840, Figure 40.1

Replace with:

The ResEditor Utility

Chapter 41

None

Chapter 42

None

Chapter 43

None

Chapter 44

Page 938, Table 44.4

Replace with:

Permission Description
Environment Read and write environment variables
FileDialog Read access to a file
FileIO Append, read, or write to a file
IsolatedStorageFile Controls access and amount of virtual file system
IsolatedStorage Control access and amount of generic isolated storage
Principal Role-based security checks
PublisherIdentity Access for a software publisher
Reflection Can use C# reflection
Registry Access operating system registry
Security Security permissions that can be invoked
SiteIdentity Access to software from a specific Web site
StrongName Access to assembly with a specific strong name
UI User interface and clipboard
URL Access to software from a location on the Internet
Zone Access to specified zones

Chapter 45

None

Chapter 46

None

Chapter 47

None

Appendix A

None

Appendix B

None