Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading and invoking functions automatically by down casting the parameter

Tags:

c#

.net

I have a base class called User.

I have 2 derived classes from User called DerivedUser, OtherDerivedUser

I have the following code:

 User user = newUser.CreateUserByType();
 SendNewUser(user); 

I don't want to perform an if or switch statement and then to perform a downcast to the derived types.

I just want to perform a call with one line statement.

 SendNewUser(user);

I want **clean code with a one-liner*.

This method according to the type will "know" dynamically which method to invoke.

I have 2 functions called SendNewUser which are overloaded by the derived type.

Is there a way invoke the correct function by downcasting to the right derived class (I don't want to explicitly cast)

   private static void SendNewUser(DerivedUser user){
       ...
      }

     private static void SendNewUser(OtherDerivedUser user){
       ...
      }
like image 975
Tal Avissar Avatar asked Jun 21 '17 11:06

Tal Avissar


3 Answers

No, there is no way to do this automatically.

You have a few options:

  1. Move SendNewUser into the DerivedUser and OtherDerivedUser class. In that way you can simply overload the method and you just need to call user.SendNewUser().

  2. Detect the type and call the appropriate method:

    public void SendNewUser(User user)
    {
        if (user is DerivedUser)
        {
            SendNewUserInternal((DerivedUser)user);
        }
        else if (user is OtherDerivedUser)
        {
            SendNewUserInternal((OtherDerivedUser)user);
        }
        else
        {
            throw new InvalidArgumentException("Wrong user type.");
        }
    }
    

As you can see, that option is quite error prone and needs work for every new derived class you introduce. I would stick with option 1 if you can.

like image 147
Patrick Hofman Avatar answered Nov 01 '22 05:11

Patrick Hofman


Yes, with pattern matching in C# 7:

switch (user)
{
    case DerivedUser u:
        SendNewUser(u);
        break;
    case OtherDerivedUser u:
        SendNewUser(u);
        break;
    default:
        throw new InvalidOperationException("Where did that come from?");
}

You can use pattern matching with if as well, although it won't improve readability all that much in this case:

if (user is DerivedUser u) {
    SendNewUser(u);
}
else if (user is OtherDerivedUser u) {
    SendNewUser(u);
}
else {
    throw new InvalidOperationException("Where did that come from?");
}
like image 3
Panagiotis Kanavos Avatar answered Nov 01 '22 06:11

Panagiotis Kanavos


I don't want to perform if or switch statement and then to perform a downcast to the derived types.

Just add dynamic to the function argument:

User user = newUser.CreateUserByType();
SendNewUser((dynamic)user); 

Also see this example:

public class Program
{
    public static void Main()
    {
        Base ba = new A();
        Do((dynamic)ba);
        ba = new B();
        Do((dynamic)ba);
    }

    public static void Do(A a)
    {
        System.Console.Write("A");
    }

    public static void Do(B b)
    {
        System.Console.Write("B");
    }
}

public class Base{}
public class A : Base{}
public class B : Base{}

Gives the output:

AB
like image 3
adjan Avatar answered Nov 01 '22 07:11

adjan