Home > OS >  C# Pass various class objects to a single method dynamically
C# Pass various class objects to a single method dynamically

Time:05-24

Lets say that I have two classes and I want to create one method that will process data from two classes, how can I setup a method that will accept both where I can create them into objects of their type?

Public classs Car:Wheel
{

  public Color color {get; set;}
}

Public class Bike:Wheel

{
public bool hasRadio {get ; set;} 
public Color color {get; set;} 
}

Public class Wheel
{
  public WheelRimType {get; set;}
  public int WheelSize {get; set;} 
}

I want to pass either the class of car or bike to a method dynamically . When in that method how can transform it to the correct object so that I don't have to write the same method twice for each object?

Car c = new Car();
Bike b = new Bike();

ValidateVehichle(c);

private void ValidateVehicle(Type T??)
{
//convert to either car or bike here
} 

CodePudding user response:

  1. Your car and bike "have" wheels, but are not "wheels", so you may want to read more about the has-a-is-a terminology when thinking about inheritance: has-a-is-a-terminology-in-object-oriented-language

  2. I believe you'd be better served creating a base class for Car and Bike and placing a Validation method in this base class which can then be implemented in Car and Bike. Something like the following:

  3. The base class VehicleBase would contain the common properties, color and Wheels properties following the "has-a" logic, in the example a VehicleBase would contain an IEnumerable<T> where T is Wheel, in which the vehicle could have zero or more wheels.


public abstract class VehicleBase
{
   public abstract bool Validate();
   public Color color { get; set;}
   public IEnumerable<Wheel> Wheels {get; set;}
}

public class Car : VehicleBase
{
   public override bool Validate()
   {
      //do Car validation
   }
}

public class Bike : VehicleBase
{
    public bool hasRadio {get ; set;} 
    public override bool Validate()
    {
      //do Bike validation
    }
}

public class Wheel
{
    public WheelRimType { get; set;}
    public int WheelSize {get; set;} 
}

CodePudding user response:

two classic possibilites

class Vehicle{

}

class Car : Vehicle{
}

class Bike : Vehicle{

}

then you can do

private void ValidateVehicle(Vehicle v)
{
//convert to either car or bike here
} 

The idiomatic way to do validatin would in fact to have the following

abstract class Vehicle{
      virtual bool Validate();
}

class Car : Vehicle{
     override bool Validate(){
     }
}

class Bike : Vehicle{
     override bool Validate(){
     }

}

the you would simply do vobj.Validate()

where vobj is an instance of a vehicle

also doable with interface

interface IVehicle{

}

class Car : IVehicle{
}

class Bike : IVehicle{

}

and

private void ValidateVehicle(Vehicle v)
{
//convert to either car or bike here
} 

CodePudding user response:

use Generics:

ValidateVehichle<Car>(car);

private void ValidateVehicle<T>(T vehicle)
{
    // no convertion needed. use T as the type of the object
    T vehicle2 = vehicle;
    .....
} 

more on generics: https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics

CodePudding user response:

You can use generics and do something like this:

void Main()
{
    Car car = new Car();
    car.color = Color.Black;
    car.WheelSize = 22;
    
    ValidateVehicle<Car>(car)
}

private void ValidateVehicle<T>(T vehicle)
{
    // You still need to determine what time this object is
    T someVehicle = vehicle;
    Console.WriteLine("This is a generic method");
}

You could alternatively use overload methods too. You can have one name of a method with infinite overloads like this:

void Main()
{
    Car car = new Car();
    car.color = Color.Black;
    car.WheelSize = 22;
    
    Bike bike = new Bike();
    bike.color = Color.Red;
    bike.hasRadio = false;
    bike.WheelSize = 12;
    
    ValidateVehicle(car);
    ValidateVehicle(bike);
    
}

// You can define other methods, fields, classes and namespaces here
public class Car: Wheel
{
  public Color color { get; set; }
}

public class Bike : Wheel
{
    public bool hasRadio { get; set; }
    public Color color { get; set; }
}

public class Wheel
{
    public int WheelSize { get; set; } 
}

private void ValidateVehicle(Car car)
{
    Console.WriteLine("This is your car method");
}

private void ValidateVehicle(Bike bike)
{
    Console.WriteLine("This is your bike method");
}

output is:

This is your car method
This is your bike method

CodePudding user response:

The typical solution would be introduce a common interface, so that ValidateVehicle can work with either type:

public interface IVehicle{
    Color color {get; set;}
}

public class Car:Wheel, IVehicle {
    public Color color {get; set;}
}
public class Bike:Wheel, IVehicle
{
   public bool hasRadio {get ; set;} 
   public Color color {get; set;} 
}

private void ValidateVehicle(IVehicle vehicle)
{
   // Implementation here
}

This obviously require IVehicle to expose all methods and properties that are used by ValidateVehicle.

If the validation logic is different for cars and bikes you should just place the validation method on your vehicle type. This way each vehicle can be validates in their own way.

public interface IVehicle{
    Color color {get; set;}
    bool ValidateVehicle();
}

A third way would be to use type checks:

private void ValidateVehicle(object vehicle)
{
   if(vehicle is Car car){
      ...
   }
   if(vehicle is Bike bike){
      ...
   }
}

But this is not as easy to maintain. Say that you introduce a motorbike, if you use a interface you just need to make your new vehicle inherit that interface, and the compiler complain if you made any mistake. If you use type-checks you need to remember all the various places you check for type and add another check for your motorbike, that can quickly become a maintenance nightmare. Because of this type checks are generally frowned upon.

I'm guessing this is for an assignment, but I dislike examples of object orientation like this. Notably a car is not a wheel, it has wheels, i.e. the wheel should be a property and not inherited.

I generally prefer geometry when demonstrating object orientation, it has plenty of examples of composition and inheritance, and is actually useful in real programs. In contrast, I have difficulty imagining where a vehicle inheritance hierarchy would actually be useful.

  • Related