开发者

InvalidCastException was unhandled

Just have a quick question... any help would be greatly appreciate!

I'm writing a database. I have a class called "Mechanism" which is inherited by two other classes called "motorcycle" and "automobile." How would i go开发者_如何学C about printing the contents of motorcycle or automobile - depending on what the user has decided to enter into the database?

this is what i have so far, it's giving me this error: InvalidCastException was unhandled. Unable to cast object of type "ConsoleApplication1.Automobile" to type "ConsoleApplication1.Motorcycle"

foreach (Mechanism m in mechanisms)
{
    //ptr = m;
    if (flagAuto == true)
    {
        Mechanism ptr = null;
        ptr = m;
        Console.WriteLine("ptr = " + ptr);
        Console.WriteLine("ptr2 = " + ptr2); 
        ptr2 = (Automobile)ptr;
        Console.WriteLine("inside Auto");
        ofp.WriteLine("" + (ptr2.getManufacturer()));
        ofp.WriteLine("" + ptr2.getModel());
        ofp.WriteLine("" + ptr2.getModelYear());
        ofp.WriteLine("" + ptr2.getVIN());
        ofp.WriteLine("" + ptr2.getInitialPurchasePrice());
        ofp.WriteLine("" + ptr2.getPurchaseDate());
        ofp.WriteLine("" + ptr2.getSizeOfEngine());
        ofp.WriteLine("" + ptr2.getTypeOfFuel());
        ofp.WriteLine("" + ptr2.getNumberOfDoors());
        ptr2 = null;
        ptr = null; 
        Console.WriteLine("finishinge Auto");
    }
    else if (flagMotor == true)
    {
        Mechanism ptr = null;
        ptr = m;
        Console.WriteLine("ptr = " + ptr);
        Console.WriteLine("ptr2 = " + ptr1); 
        Console.WriteLine("inside Motor");
        ptr1 = (Motorcycle)ptr;
        ofp.WriteLine("" + ptr1.getManufacturer());
        ofp.WriteLine("" + ptr1.getModel());
        ofp.WriteLine("" + ptr1.getModelYear());
        ofp.WriteLine("" + ptr1.getVIN());
        ofp.WriteLine("" + ptr1.getInitialPurchasePrice());
        ofp.WriteLine("" + ptr1.getPurchaseDate());
        ofp.WriteLine("" + ptr1.getSizeOfEngine());
        ofp.WriteLine("" + ptr1.getTypeOfMotorcycle());
        ptr1 = null;
        ptr = null; 
        Console.WriteLine("finishing Motor");
    }

the flags are supposed to keep track of which type of vehicle is trying to be entered into my database - then it should write it out to a text file..


That means the value of the flag is wrong.

You should do this instead:

if (m is Automobile)
{
    Automobile autoMobile = m as Automobile;
    //.. work with autoMobile
}
else if (m is Motorcycle)
{
    Motorcycle motorCycle = m as Motorcycle;
    //.. work with motorCycle 
}

By the way, you're doing the same thing in the both branch. That implies, that you could implement them in a base class (Mechanism), call those methods on m object.


Not all Mechanism can be cast to Motorcycles. In your particular case, you have an instance of Automobile and you are trying to cast it to a Motorcycle (that's what the exception message says). You can't do that (A Dog can not be converted to Cat even though both are Animal).

Instead of doing type-by-type logic, why don't you just override ToString or provide a method on Mechanism that can be overridden by Motorcycle and Automobile. Then you can just invoke ToString or that method, without evening having to worry about the particular type. That's polymorphism! Here's a rudimentary example to get you started.

class Mechanism {
     public virtual IEnumerable<string> GetDetails() {
          // assume these are all defined by Mechanism, omitted here for brevity
          yield return this.getManufacturer();
          yield return this.getModel();
          yield return this.getModelYear();
          yield return this.getVIN();
          yield return this.getInitialPurchasePrice();
          yield return this.getPurchaseDate();
          yield return this.getSizeOfEngine();
          yield return this.getTypeOfFuel();
     }
}

class Automobile : Mechanism {
     public override IEnumerable<string> GetDetails() {
          foreach(var detail in base.GetDetails()) {
               yield return detail;
          }
          yield return this.getNumberOfDoors();
     }
}

class Motorcycle : Mechanism {
     public override IEnumerable<string> GetDetails() {
         foreach(var detail in base.GetDetails()) {
             yield return detail;
         }
         yield return this.getTypeOfMotorCycle();
     }
}

Then you can just say:

foreach(var mechanism in mechanisms) {
    foreach(var detail in mechanism.GetDetails()) {
        ofp.WriteLine(detail);
    }
}

Aye, it's beautiful!


Well, simply put, your flagMotor is lying to you; the object is an Automobile, as the error message says, but you're trying to cast it to Motorcycle. You need to find out why your flags are set wrong.

Or you could eliminate the flags altogether, and use C#'s is operator:

if (m is Automobile) {
    // ...
} else  if (m is Motorcycle) {
    // ...
}


As Ernest Friedman-Hill mentions, with your current archetuture, the flags are not being set correctly.

It may be worth mentioning, (not having seen the full source for your classes), it looks like perhaps your object hierarchy isn't quite standard OOP. You should probably have the Mechanism class contain all members that are common between the various classes that derive from Mechanism, and override any methods that may differ between the two but make sense to have in both. This also makes a decent case for Mechanism to be an Abstract Base Class.

A ridiculously over simplified example follows:

public class Mechanism {
    public string Vin {get;set;}
}

public class Auto : Mechanism {
    public int NumberOfDoors {get;set;

    public override string ToString() {
        return string.Format("{0}, {1}", Vin, NumberOfDoors);
    }
}

public class Motorcycle : Mechanism {
    public string TypeOfMotorcycle {get;set; }

    public override string ToString() {
        return string.Format("{0}, {1}", Vin, TypeOfMotorcycle );
    }
}

foreach (Mechanism m in mechanisms) {
    Console.Print(m.ToString());
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜