Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switch with Object Instances

Edit

Here is a different version of the code that makes it a little more clear about what I am trying to do:

class Program
{
    static void Main(string[] args)
    {
        RepairCar(Car.Ferrari);
    }

    public static void RepairCar(Car BrokenCar)
    {
        switch (BrokenCar)
        {
            case Car.Ferrari:
                Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;

            case Car.BMW:
                Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;

            case Car.Audi:
                Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;

            default:
                Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;
        }
    }

    public static double CalculateInsurance(Car BrokenCar)
    {
        return (BrokenCar.Price / 10);
    }

}

public class Car
{
    public double Price;
    public int MaxSpeed;
    public int MinSpeed;

    public Car(double Price, int MaxSpeed, int MinSpeed)
    {
        this.Price = Price;
        this.MaxSpeed = MaxSpeed;
        this.MinSpeed = MinSpeed;
    }

    public static Car Ferrari = new Car(100000, 250, 10);
    public static Car Audi = new Car(50000, 120, 30);
    public static Car BMW = new Car(35000, 80, 75);
}

As written, this won't compile because it will not let me switch the BrokenCar in the RepairCar method. Any suggestions?

Original Post

I am trying to create an object that can store static properties and, more importantly be able to be switched over - here is an example -

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(GetMaxSpeed(Car.Ferrari));
        Console.ReadLine();
    }

    public static int GetMaxSpeed(Car ModelType)
    {
        switch (ModelType)
        {
            case Car.Ferrari:
                return Car.Ferrari.MaxSpeed;

            case Car.VW:
                return Car.VW.MaxSpeed;

            case Car.AstonMartin:
                return Car.AstonMartin.MaxSpeed;
        }
    }

    public class Car
    {
        public int MinSpeed;
        public int MaxSpeed;

        public Car(int MinSpeed, int MaxSpeed)
        {
            this.MinSpeed = MinSpeed;
            this.MaxSpeed = MaxSpeed;
        }

        public static Car Ferrari = new Car(30, 240);
        public static Car VW = new Car(10, 50);
        public static Car AstonMartin = new Car(75, 180);
    }

}

Does anyone have any ideas?

EDIT

This example describes a larger, more complex system. To illustrate why I would need to do it this way, see the following update:

    public static void OnCarSale(Car CarSold)
    {
        double LuxuryTax = 75;

        switch (CarSold)
        {
            case Car.Ferrari:
                Console.WriteLine("Total Price: {0}", Car.Ferrari.Price + LuxuryTax);
                break;

            case Car.VW:
                Console.WriteLine("Total Price: {0}", Car.VW);
                break;

            case Car.AstonMartin:
                Console.WriteLine("Total Price: {0}", Car.Ferrari.Price + LuxuryTax);
                break;
        }
    }

This would get called by an event outside of this class.

like image 319
William Avatar asked Oct 31 '11 17:10

William


5 Answers

To directly answer your question, make ModelType an enum and switch off that value. Have the Car type have a ModelType property called "Model" in the example below.

public enum ModelType
{
    Ferrari = 0,
    AstonMartin = 1
}

public int GetMaxSpeed( Car car )
{
    switch( car.Model )
    {
        case Ferrari:
           return 300;
        case AstonMartin:
           return 250;
        default:
           return 100;
    }
}

But the better question is, why aren't you using polymorphism? You can make Car a base type and have different models inherit from it. The base Car type should have a MaxSpeed property. No matter what subclass you have inheriting from Car, you can reference MaxSpeed to get the property value for that particular model. This might be over-complicating your example (homework?), but it would make your code more OOP.

public class Car
{
    private int _maxSpeed = 200;
    public int MaxSpeed
    {
        get { return _maxSpeed; }
        protected set { _maxSpeed = value; }
    }
}

public class Ferrari : Car
{
    public Ferrari()
    {
        // Constructor 
        this.MaxSpeed = 250;
    }
}

// client code
public void DoStuff()
{
   Car ferrari = new Ferrari();
   Console.WriteLine( ferrari.MaxSpeed );
}

If you want to have a Garage class with a list of cars, it would look something like the following. Keep in mind this is very crude code but it shows you what I'm talking about in the comments.

public class Garage
{
    private List<Car> Cars { get; set; }

    public Garage()
    {
       this.LoadCars();
    }

    private void LoadCars()
    {
       this.Cars = new List<Car>();
       this.Cars.Add( new Ferrari() );
       this.Cars.Add( new AstonMartin() );
    }

    public int GetMaxSpeedOfAllCars()
    {
        int maxSpeed = 0;

        foreach( Car car in this.Cars )
        {
            if( car.MaxSpeed > maxSpeed )
            {
                maxSpeed = car.MaxSpeed;
            }
        }

        return maxSpeed;
    }

}
like image 107
Jordan Parmer Avatar answered Nov 17 '22 13:11

Jordan Parmer


It depends on what you want to do with it. If the "switch" is to give the cars extra behaviour, put it in the class itself. For example, in your case you've already got the appropriate field (ick, public fields, but...) You can just use:

public static int GetMaxSpeed(Car car)
{
    return car.MaxSpeed;
}

In other cases, you might give the type a method, and you can use nested classes to implement the methods differently based on the different values. Give the "base" class a private constructor and abstract methods, then create derived classes as nested classes so they can still use the private constructor and expose specific values. I call these types "smart enums".

If you want to map each value to another value, use a Dictionary<Car,string> (or whatever). If you want to map each value to an action, use a Dictionary<Car, Action>.

Basically you won't be able to use switch unless you have an enum or some integral type... and that would usually be a pain. Using a dictionary is often a simpler approach.

If you can give a more realistic example which isn't so easily solved, we can help more...

like image 8
Jon Skeet Avatar answered Nov 17 '22 13:11

Jon Skeet


Starting C# 7.0 you may use pattern matching:

       public static void RepairCar(Car BrokenCar)
    {
        switch (BrokenCar)
        {
            case { } car when car == Car.Ferrari:
                Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;

            case { } car when car == Car.BMW:
                System.Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;

            case { } car when car == Car.Audi:
                Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;

            default:
                Console.WriteLine("${0} of Insurance Needed", CalculateInsurance(BrokenCar));
                // 
                // Repair Algorithm Here
                //
                break;
        }
    }
like image 3
Alexander Vologin Avatar answered Nov 17 '22 12:11

Alexander Vologin


You won't be able to do this, because C# only supports compile-time constants for switch cases. Instead you should use if/else blocks.

like image 2
Thomas Levesque Avatar answered Nov 17 '22 11:11

Thomas Levesque


I would, just on general principles, create a Dictionary of these instances (or just maintain a List) instead of switching on them. Switch statements are sometimes necessary, but they are rarely "SOLID" code; any time a new type of Car is created, you will have to change the switch statement to handle this new case.

static void Main(string[] args)
{
    Console.WriteLine(GetMaxSpeed(Car.Ferarri));
    Console.ReadLine();
}

public static int GetMaxSpeed(string ModelType)
{
    foreach(var car in Car.Cars)
       if(car.Name == ModelType)
          return car.MaxSpeed;
}

public enum Car
{
    public int MinSpeed;
    public int MaxSpeed;
    public string Name;

    public Car(string Name, int MinSpeed, int MaxSpeed)
    {
        this.Name = Name;
        this.MinSpeed = MinSpeed;
        this.MaxSpeed = MaxSpeed;
    }

    public static List<Car> Cars = new List<Car>
    {
       new Car(Car.Ferrari, 30, 240);
       new Car(Car.VW, 10, 50);
       new Car(Car.AstonMartin, 75, 180);        
    }

    public static const string Ferrari = "Ferrari";
    public static const string VW = "VW";
    public static const string AstonMartin= "AstonMartin";
}

If you simply had to switch on object references, try switching on a private integral-type field uniquely identifying that car; an ID field. Then, you can compare IDs within the switch statement instead of references.

static void Main(string[] args)
{
    Console.WriteLine(GetMaxSpeed(Car.Ferrari));
    Console.ReadLine();
}

public static int GetMaxSpeed(Car ModelType)
{
    switch (ModelType.Id)
    {
        case Car.Ferrari.Id:
            return Car.Ferrari.MaxSpeed;

        case Car.VW.Id:
            return Car.VW.MaxSpeed;

        case Car.AstonMartin.Id:
            return Car.AstonMartin.MaxSpeed;
    }
}

public class Car
{
    public int MinSpeed;
    public int MaxSpeed;
    internal int Id;

    public Car(int MinSpeed, int MaxSpeed)
    {
        this.MinSpeed = MinSpeed;
        this.MaxSpeed = MaxSpeed;
    }

    public static Car Ferrari = new Car(30, 240){Id = 1};
    public static Car VW = new Car(10, 50){Id = 2};
    public static Car AstonMartin = new Car(75, 180){Id = 3};
}
like image 1
KeithS Avatar answered Nov 17 '22 12:11

KeithS