Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Visual Studio 2005 (2006) [eng]

.pdf
Скачиваний:
135
Добавлен:
16.08.2013
Размер:
21.9 Mб
Скачать

Chapter 29

If you want to treat all warnings as errors so you can be sure of the cleanest compilation of your solution, you can check the “Treat all warnings as errors” checkbox (off by default). This will consider all warnings except for implicit conversions of Integer types to String types as errors, and will not allow the compilation to succeed until they are addressed as errors.

If, however, you want to do the reverse and ignore the warnings, you can do this by checking the Disable All Warnings option. These options are mutually exclusive; and if you have both checked, the Disable All Warnings option takes precedence.

Warnings Not Displayed by Default

A number of individual warnings can have their behavior set independently of the global option for treating warnings. Some of these warnings are not displayed by default, but can be the source of issues in your program’s execution. You should review each of these warnings and determine whether they should be activated as either warnings (displaying a warning at compilation but allowing the build to continue) or errors that stop the build process, or left deactivated.

Implicit conversion

Implicit conversion issues can cause unexpected results in your program execution because the different variable objects may be of different types, or the information may not be translated properly across types. When you don’t code an explicit conversion, the runtime attempts to implicitly convert the source object to the destination type. The following code shows an example of an implicit conversion:

Dim myDocObject As Object = New Xml.XmlDocument Dim myDoc As Xml.XmlDocument

myDoc = myDocObject

By default, this option is turned off and any implicit conversions are ignored in the compilation of your program. Turning this option on to Warning will mark any type conversions as warnings so you are informed about them. If you don’t want the program to build with implicit conversions present in your code, set the option to Error.

To avoid warnings or errors when this condition is activated, always explicitly convert your object types. The preceding sample code could be amended to explicitly convert the Object to an XmlDocument type like so:

Dim myDocObject As Object = New Xml.XmlDocument Dim myDoc As Xml.XmlDocument

myDoc = CType(myDocObject, Xml.XmlDocument)

This condition is slightly different from Option Strict, as it ignores the implicit conversion of numeric types such as an Integer to a String, so it may be a better option for your environment than activating Option Strict.

Late binding; call could fail at run time

Some applications require late binding of objects, but the actual process of late binding has risks because at runtime the application may fail when it tries to instantiate the late-bound object. The usual reason for late-binding failures is that the object type doesn’t exist on the system or is not registered correctly. To avoid these issues, make sure you always write code to handle the unexpected situation.

376

Preemptive Error Correction

By default, this condition is turned off, meaning you won’t be informed of any late binding in your code, but you may want to set it to Warning level so you will always be aware of any late binding in your application code.

Implicit type; object assumed

An old programming practice was to simply define objects without identifying their type. In Visual Basic 6 this would result in variables of the Variant type, but in Visual Basic 2005 the result is a generic Object type. Object variables can contain almost any other type of object but they do not provide you with the safe compilation option of ensuring that you only use valid members of the object.

In Visual Basic 2005, this kind of definition is accepted by default, but it can be changed through the Implicit type; object assumed condition. It is good programming practice to explicitly define your variables to be a specific type, so you may want to set this option to either Warning or Error. The following definition would generate an Error or a Warning if you activate this condition:

Dim myObject

Other Customizable Warnings

In addition to the previous list of warnings that are not processed by default, a number of other warnings in the Conditions list are set to a warning level by default. Changing their individual settings enables you to mark them as compilation errors, or to be reduced to informational conditions that do not display in the compilation output or Error List.

Use of variable prior to assignment

Most commonly, you’ll see this condition displayed when you define an object or String and then assign it to another variable without first initializing it to a value. The following code demonstrates when this warning will be displayed:

Dim myString As String Dim myString2 As String myString2 = myString

Because the code tries to assign the value of myString to the myString2 variable, without myString being set to a value first, a warning is displayed.

If you want to ensure that your objects are always initialized with a proper value before assigning them, set this condition to Error.

Function/Operator without return value

The old way of writing functions in Visual Basic was to set an implicitly defined variable of the same name as the function to whatever value you needed to return. Once the value was set, the function would continue until it reached the end of the function definition or it encountered an Exit Function statement.

It was possible to perform code in the function without explicitly setting this return value, which would result in a default value being returned. The following function definition illustrates how a simple function might look in Visual Basic 6:

377

Chapter 29

Public Function myTest(theVariable As Integer) As Boolean

If theVariable > 10 Then myTest = True

End Function

With Visual Basic 2005, values are returned to the calling code by using the Return statement. As soon as the processing of the function encounters a Return statement, it returns to the calling code with the value specified, and ignores the remainder of the function. While the situation can occur where the return value is not set, Visual Basic 2005 regards this as poor programming form that can result in unexpected results (which was not the case in Visual Basic 6).

To ensure that you’re aware of any functions that do not return values on all logic paths, this condition is set to Warning by default. However, if you feel that you should explicitly set a return value under all circumstances, you can set this to Error and stop the solution from building if the return value isn’t set. The following function illustrates how the Visual Basic 6 definition would be converted to Visual Basic 2005:

Public Function myTest(theVariable As Integer) As Boolean

If theVariable > 10 Then Return True

End Function

To stop this condition from being processed, you would need to add an additional Return statement in the event that theVariable was 10 or less, as the following listing demonstrates:

Public Function myTest(theVariable As Integer) As Boolean

If theVariable > 10 Then Return True

Return False

End Function

Unused local variable

The Unused local variable condition is self-explanatory. Whenever the compiler identifies a variable that has been defined but not used in the associated code block, it will generate a warning by default. This is a very handy feature for reviewing large programs for variables that are not used.

To quickly locate and remove all unused variables from your code, set this condition to Error and step through the compilation errors on the Error List.

Instance variable accesses shared member

You may get unexpected results when performing a shared method in a class definition from an instance. For example, you might have a class theClass with a shared function of myFunc. When you create an instance of theClass, it appears that you can call the myFunc from the instance, as the following code demonstrates:

Public Class theClass

Shared Function myFunc() As Boolean ‘ some code

End Function End Class

...elsewhere in the code

Dim xx As New theClass xx.myFunc()

378

Preemptive Error Correction

However, this practice obscures the functionality of shared members, which provide a single access for all instances of the method or property. Better programming practice is to use the class definition to call upon shared members, which means that instead of using the xx.myFunc() statement, you would program theClass.myFunc() in its place.

To ensure that you always review these kinds of situations, the Instance variable accesses shared member condition is set to Warning, but you can either turn it off, if your in-house programming style requires that you always call shared members through an instance, or set it to the Error level so the solution won’t be built when such instances are encountered in the code.

When this condition is set to Error or Warning, the Smart Compile Auto Correction feature will display a suggested solution that involves converting the access to the class instead of an instance.

Recursive operator or property access

The Recursive operator or property access condition is set to Warning by default, and flags any instances where your code refers to the function or property that contains the code itself. The following code demonstrates this problem by defining a Property called myProp, and then attempting to set and return myProp in the Get and Set accessors of the property definition:

Public Property myProp() As String

Get

Return myProp

End Get

Set(ByVal value As String) myProp = value

End Set End Property

You will most likely want to set this to an Error level so you can fix the code — recursively calling a property in this way is never going to work.

Setting this property to Warning or Error won’t flag recursive functions — which is a good thing because a lot of programming techniques use them!

Duplicate or overlapping catch blocks

The Duplicate or overlapping catch blocks condition deals with situations in which multiple Catch blocks consume the same errors, resulting in one Catch block never being reached. The following code snippet shows an instance of where this might occur — the generic Exception Catch block appears before the more specific ApplicationException block:

Try

...some code...

Catch ex As Exception MessageBox.Show(ex.Message)

Catch exApp As ApplicationException MessageBox.Show(exApp.Message)

End Try

By default, this condition is set to Warning, but you will most likely want to set it to Error to ensure that you’re always aware of exception Catch blocks that cannot be processed.

379

Chapter 29

Customizing Warnings in C#

C# developers also have a way of customizing how warnings are treated in their code. As in the case of Visual Basic projects, a simple toggle option is available to treat all, some, or no warnings as errors (see Figure 29-7). The default option is to assume that all warnings are just that — warnings — allowing the compilation to complete.

However, if you want to stop the solution from being built in the event of a warning, you can change this option to either All or Specific warnings. If you are only concerned about specific warnings, you should provide a list of warning numbers separated by commas or semicolons.

Figure 29-7

You can suppress individual warnings completely by entering them in the Suppress Warnings text box. Again, you should separate the warning numbers with commas or semicolons. Any warnings entered in this area will not be displayed regardless of what other options you set.

The final way of customizing your compilation output for warnings is to set the warning level. By default this option is set to 4, which will result in all errors, warnings, and even informational messages being displayed in the output of the build process. You can fine-tune the amount of information generated in the compilation by changing this setting to a value of 0 through to 3. A value of 0 will suppress all warnings and informational messages completely, resulting in only compilation errors being displayed, while a value of 3 will display all errors and warnings but not purely informational messages.

380

Preemptive Error Correction

Using a combination of these settings, you can achieve a “perfect” compilation for your particular requirements. The idea is to set any warnings that must be dealt with as errors in the Specific Warnings option, and then suppress the less important messages and warnings. The result, once you’ve dealt with the required errors and warnings, will be a build process with a clean output.

Summar y

This chapter described the additional features Visual Studio 2005 provides to help you preempt problems in your programs. Using the Smart Compile Auto Correction feature in conjunction with customizing which warnings are displayed and how they are treated, you can build an environment that highlights the issues that are most important to you, while suppressing issues that you do not need to worry about for the particular application.

381

Strongly Typed DataSets

A large proportion of applications use some form of data storage. This might be in the form of serialized objects or XML data, but for long-term storage that supports concurrent access by a large number of users, most applications use a database. The .NET Framework includes strong support for working with databases and other data sources. This chapter examines how to use strongly typed DataSets to build applications that work with data from a database.

This examples in this chapter are based on the sample AdventureWorks database that is available as a download from www.microsoft.com.

DataSet Over view

The .NET Framework DataSet is a complex object that is approximately equivalent to an in-memory representation of a database. It contains DataTables that correlate to database tables. These in turn contain a series of Columns that define the composition of each DataRow. The DataRow correlates to a row in a database table. Of course, it is possible to establish relationships between DataTables within the DataSet in the same way that a database has relationships between tables.

One of the ongoing challenges for the object-oriented programming paradigm is that it does not align smoothly with the relational database model. The DataSet object goes a long way toward bridging this gap, as it can be used to represent and work with relational data in an object-oriented fashion. However, the biggest issue with a raw DataSet is that it is weakly typed. Although the type of each column can be queried prior to accessing data elements, this adds overhead and can make code very unreadable. Strongly typed DataSets combine the advantages of a DataSet with strong typing to ensure that data is accessed correctly at design time. This is done with the custom

Chapter 30

tool MSDataSetGenerator, which converts an XML schema into a strongly typed DataSet. In the following code snippet, you can see the difference between using a raw DataSet, in the first half of the snippet, and a strongly typed DataSet, in the second half:

‘Raw DataSet

Dim nontypedAwds As DataSet = RetrieveData()

Dim nontypedcontacts As DataTable = nontypedAwds.Tables(“Contact”) Dim nontypedfirstContact As DataRow = nontypedcontacts.Rows(0) MsgBox(nontypedfirstContact.Item(“FirstName”))

‘Strongly typed DataSet

Dim awds As AdventureWorksDataSet = RetrieveData()

Dim contacts As AdventureWorksDataSet.ContactDataTable = awds.Contact Dim firstContact As AdventureWorksDataSet.ContactRow = contacts.Rows(0) MsgBox(firstContact.FirstName)

Using the raw DataSet, both the table lookup and the column name lookup are done using string literals. As you are likely aware, string literals can be a source of much frustration and should only be used within generated code, although preferably not at all.

Adding a Data Source

You can manually create a strongly typed DataSet by creating an XSD using the XML schema editor. To create the DataSet you set the custom tool value for the XSD file to be the MSDataSetGenerator. This will create the designer code file that is needed for strongly typed access to the DataSet. In most cases, the source of your data will be a database, in which case Visual Studio 2005 provides a wizard that you can use to generate the necessary schema based on the structure of your database.

To create a strongly typed DataSet from an existing database, start by selecting Add New Data Source from the Data menu, and following these steps:

Although this functionality is not available for ASP.NET projects, a workaround is to perform all data access via a class library.

1.The first step in the Data Source Configuration Wizard is to select the type of data source to work with, as shown in Figure 30-1. In this case, you want to work with data from a database, so select the Database icon and click Next.

2.The next screen prompts you to select the database connection to use. To create a new connection, click the New Connection button, which opens the Add Connection dialog. The attributes displayed in this dialog are dependent on the type of database you are connecting to. By default the SQL Server provider is selected, as illustrated in Figure 30-2.

384

Strongly Typed DataSets

Figure 30-1

Figure 30-2

385