‘subclassName’ : cannot inherit from sealed class ‘baseclassName’ ‘className’ does not implement interface member ‘methodName’ ‘methodName’ : not all code paths return a value } expected
Trang 1Part VI The Part of Tens
Trang 2In this part
What For Dummies book would be complete without
a Part of Tens? C# is great at finding errors in your programs when you try to build them — you’ve probably noticed that However, the error messages it generates can be cryptic — you’ve probably noted that, as well Chapter 16 reviews the ten most common build-time error messages and what they most likely mean Knowledge is power, so Chapter 16 also suggests fixes for the problems that are being reported These items have been updated
to reflect a few changes in C# 2.0
Many readers will have come to C# through the most common of all object-oriented languages, C++ Chapter 17 quickly reviews the differences between the two languages, including the differences between C# generics and C++ templates
Trang 3Chapter 16
The 10 Most Common Build Errors
(And How to Fix Them)
In This Chapter
The name ‘memberName’ does not exist in the class or namespace ‘className’
Cannot implicitly convert type ‘x’ into ‘y’
‘className.memberName’ is inaccessible due to its protection level
Use of unassigned local variable ‘n’
Unable to copy the file ‘programName.exe’ to ‘programName.exe.’ The process cannot
‘subclassName.methodName’ hides inherited member ‘baseclassName.methodName’ Use the new keyword if hiding was intended
‘subclassName’ : cannot inherit from sealed class ‘baseclassName’
‘className’ does not implement interface member ‘methodName’
‘methodName’ : not all code paths return a value
} expected
C# makes the ol’ college try at finding errors in your C# code In fact, C# homes in on syntax errors like a tornado heading for a double-wide Other than really stupid mistakes like trying to compile your shopping list, the same complaints seem to pop up, over and over
This chapter describes 10 common build-time error messages A few warn-ings are in order, however First, C# can get awfully long-winded I have whit-tled down some of the error messages so that the message can fit on one page, let alone one or two lines In addition, an error message has places to insert the name of an errant data member or an obnoxious class In place of these specific names, I have inserted variableName, memberName, or
className Finally, C# doesn’t simply spit out the name of the class It prefers to tack on the full namespace name — just in case the entire error message would have been visible without scrolling over to your neighbor’s house
Trang 4The name ‘memberName’ does not exist in the class or namespace ‘className’
This error message could mean that you forgot to declare a variable, as in the following example:
for(index = 0; index < 10; index++) {
// whatever }
The variable indexis not defined anywhere (See Chapter 3 for instructions
on declaring variables.) This example should have been written as follows:
for(int index = 0; index < 10; index++)
{ // whatever }
The same applies to data members of a class (See Chapter 6.)
A more likely possibility is that you misspelled a variable name The following
is a good example:
class Student {
public string sStudentName;
public int nID;
} class MyClass {
static public void MyFunction(Student s) {
Console.WriteLine(“Student name = “ + s.sStudentName);
Console.WriteLine(“Student Id = “ + s.nId);
} }
The problem here is that MyFunction()references a data member nId
rather than the actual data member nID Although you see the similarity, C# does not The programmer wrote nId, but no nIdexists, and that’s all there
is to it The fact that nIDis lurking around the corner, alphabetically speak-ing, is irrelevant (The message here is a bit different: ‘class.memberName’ does not contain a definition for ‘variableName’ See Chapter 3 for details.)
Trang 5Less popular but still way up on the Top 10 playlist is the possibility that the variable was declared in a different scope, as follows:
class MyClass {
static public void AverageInput() {
int nSum = 0;
int nCount = 0;
while(true) {
// read in a number string s = Console.ReadLine();
int n = Int32.Parse(s);
// quit when the user enters a negative number
if (n < 0) {
break;
} // accumulate the value entered nSum += n;
nCount++;
} // now output the results Console.WriteLine(“The total is “ + nSum);
Console.WriteLine(“The average is “ + nSum / nCount);
// this generates a build time error message Console.WriteLine(“The terminating value was “ + s);
} }
The last line in this function is incorrect The problem is that a variable is lim-ited to the scope in which it is defined The variable sis not defined outside
of the while()loop (See Chapter 5.)
Cannot implicitly convert type ‘x’ into ‘y’
This error usually indicates that you’re trying to use two different variable types in the same expression — for example:
int nAge = 10;
// generates an error message int nFactoredAge = 2.0 * nAge;
The problem here is that 2.0 is a variable of type double The int nAge multi-plied by the double2.0 results in a doublevalue C# does not automatically store a doubleinto the intvariable nFactoredAgebecause information may
be lost — most notably, any fractional value that the doublemay possess
369
Chapter 16: The 10 Most Common Build Errors (And How to Fix Them)
Trang 6Some conversions are not obvious, as in the following example:
class MyClass {
static public float FloatTimes2(float f) {
// this generates a build time error float fResult = 2.0 * f;
return fResult;
} }
You may think that doubling a floatwould be okay, but that’s sort of the problem 2.0is not a float— it defaults to type double A doubletimes a
floatis a double C# does not store a doublevalue back into a float vari-able due to — you guessed it — possible loss of data; in this case, it is several digits of accuracy (See Chapter 3.)
Implicit conversions can further confuse the casual reader (that’s me on a good day) The following version of FloatTimes2()works just fine:
class MyClass {
static public float FloatTimes2(float f) {
// this works fine float fResult = 2 * f;
return fResult;
} }
The constant 2is of type int An inttimes a floatis a float, which can be stored in the floatvariable fResult
The implicit conversion error message can also arise when performing opera-tions on “unnatural” types For example, you cannot add two charvariables, but C# can convert charvariables into intvalues for you when necessary to get the job done This leads to the following:
class MyClass {
static public void SomeFunction() {
char c1 = ‘a’;
char c2 = ‘b’;
// I don’t know what this even means, but it’s illegal anyway - not for the // reason you think
char c3 = c1 + c2;
}
Trang 7Adding two characters together makes no sense, but C# tries anyway Because addition isn’t defined for type char, it converts c1and c2into intvalues and then performs the addition (charis technically listed as an integral type.) Unfortunately, the resulting intvalue cannot be converted back into a char
without some help (See Chapter 3.) Most, but not all, conversions are okay with an explicit cast Thus, the follow-ing function works without complaint:
class MyClass {
static public float FloatTimes2(float f) {
// this works OK with the explicit cast float fResult = (float)(2.0 * f);
return fResult;
} }
The result of 2.0 * fis still of type double, but the programmer has indi-cated that she specifically wants the result down-converted to a float, even
in the unlikely event that it results in the loss of data (See Chapter 3.)
A second approach would be to make sure that all constants are of the same type, as follows:
class MyClass {
static public float FloatTimes2(float f) {
// this works OK because 2.0F is a float constant float fResult = 2.0F * f;
return fResult;
} }
This version of the function uses a constant 2.0 of type floatrather than the default double A floattimes a floatis a float
‘className.memberName’ is inaccessible due to its protection level
This error indicates that a function is trying to access a member to which it does not have access For example, a method in one class may be trying to access a private member in another class (see Chapter 11), as shown in the following code:
371
Chapter 16: The 10 Most Common Build Errors (And How to Fix Them)
Trang 8public class MyClass {
public void SomeFunction() {
YourClass uc = new YourClass();
// this doesn’t work properly because MyClass can’t access // the private member
uc.nPrivateMember = 1;
} } public class YourClass {
private int nPrivateMember = 0;
}
Usually, the error is not so blatant Often, you’ve simply left the descriptor off
of either the member object or the class itself By default, a member of a class
is privatewhile a class is internal Thus, nPrivateMemberis still private in the following example:
class MyClass // undeclared class access level defaults to internal {
public void SomeFunction() {
YourClass uc = new YourClass();
// this doesn’t work properly because MyClass can’t access the // private member
uc.nPrivateMember = 1;
} } public class YourClass {
int nPrivateMember = 0; // this member is still private }
In addition, even though SomeFunction()is declared public, it still can’t be accessed from classes in other modules because MyClassitself is internal The moral of the story is this: “Always specify the protection level of your classes and their members.” A lemma is “Don’t declare public members in
a class that itself is internal — it doesn’t do any good and it’s just confusing.”
Use of unassigned local variable ‘n’
Just like it says, this message indicates that you declared a variable but didn’t give it an initial value This is usually an oversight, but it can occur when you really meant to pass a variable as an outargument to a function, as shown in the following example:
Trang 9public class MyClass {
public void SomeFunction() {
int n;
// this is OK because C# only returns a value in n; it does not // pass a value into the function
SomeOtherFunction(out n);
} public void SomeOtherFunction(out int n) {
n = 1;
} }
In this case, nis not assigned a value inside of SomeFunction(), but it is in
SomeOtherFunction() SomeOtherFunction()ignores the value of an out
argument as if it didn’t exist — which it doesn’t in this case (Chapter 3 covers variables Chapter 7 explains out.)
Unable to copy the file ‘programName.exe’
to ‘programName.exe’ The process cannot
Usually, this message repeats multiple times In almost every case, it means you forgot to terminate the program before you rebuilt it In other words, you did the following:
1 You successfully built your program (I assume that it’s a console appli-cation, although it can happen to any C# output.)
2 When you ran the program by choosing Debug➪Start Without Debugging, you got to the message Press Enter to terminate, but in your haste, you didn’t press Enter So, your program is still executing
Instead, you switched back to Visual Studio 2005 to edit the file
Note: If you run the program by choosing Debug➪Start Debugging and
forget to terminate, you’re simply asked whether you want to stop debugging
3 You tried to build the program again with the new updates At this point, you get this error message in the Error List window
An executable (.EXE) file is locked by Windows until the program actually quits Visual Studio cannot overwrite the old EXEfile with the new version until the program terminates
373
Chapter 16: The 10 Most Common Build Errors (And How to Fix Them)
Trang 10To get rid of the error, switch to the application and terminate it In the case
of a console application, just press Enter to terminate the program You can also terminate the program from within Visual Studio 2005 by choosing Debug➪Stop Debugging After the older program has terminated, rebuild the application
If you can’t get rid of the error by terminating the program, the directory may
be messed up Close the solution, exit Visual Studio 2005, reboot, and then reopen the solution If that doesn’t work, I’m sorry — punt
‘subclassName.methodName’ hides inherited member ‘baseclassName.
methodName’ Use the new keyword
if hiding was intended
With this message, C# is telling you that you’ve overloaded a method in a base class without overriding it (See Chapter 13 for details.) Consider the following example:
public class BaseClass {
public void Function() {
} } public class SubClass : BaseClass {
public void Function() // here’s the overload {
} } public class MyClass {
public void Test() {
SubClass sb = new SubClass();
sb.Function();
} }
Trang 11The function Test()cannot get at the method BaseClass.Function()from the subclass object sbbecause it is hidden by SubClass.Function() You intended to do one of the following:
You intended to hide the base class method In that case, add the new
keyword to the SubClassdefinition, as in the following example:
public class SubClass : BaseClass {
new public void Function() {
} }
You meant to inherit the base class polymorphically, in which case you should have declared the two classes as follows:
public class BaseClass {
public virtual void Function() {
} } public class SubClass : BaseClass {
public override void Function() {
} }
See Chapter 13 for details
This is not an error — just a warning in the Error List window
‘subclassName’ : cannot inherit from sealed class ‘baseclassName’
This message indicates that someone has sealed the class, so you can’t inherit from it or change any of its properties Typically, only library classes are sealed You can’t get around your inability to inherit from the sealed class, but try using the class via a HAS_A relationship (See Chapter 13.)
375
Chapter 16: The 10 Most Common Build Errors (And How to Fix Them)
Trang 12‘className’ does not implement interface member ‘methodName’
Implementing an interface represents a promise to provide a definition for all the methods of that interface This message says that you broke that promise
by not implementing the named method The following possible reasons exist:
Your dog ate your homework Basically, you just forgot or were unaware
of the method Be more careful next time
You misspelled the method or gave the wrong arguments
Consider the following example:
interface Me {
void aFunction(float f);
} public class MyClass : Me {
public void aFunction(double d) {
} }
The class MyClassdoes not implement the interface function aFunction (float) The function aFunction(double)doesn’t count because the argu-ments don’t match
Go back to the drawing board and continue implementing methods until the interface has been completely fulfilled (See Chapter 14.)
Not fully implementing an interface is essentially the same thing as trying to create a concrete class from an abstract one without overriding all the abstract methods
‘methodName’ : not all code paths return a value
With this message, C# is telling you that your method was declared nonvoid and one or more paths don’t return anything This can happen in either of the following two ways:
You have an ifstatement that has a return without a value specified
More likely, you calculated a value and never returned it