Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can A subclass be downcast while sent as a parameter to an overloaded function

I have a superClass called Block and another 3 subclasses. the class I want to implement contains 3 overloaded functions each one takes an object of one of the subclasses as a parameter. When I use one of these function, I only have a Block object (An object from the superClass). My question is what is the cleanest way to choose which function to call.

What I did until now is if conditions on the object type then casting it. but it seems unclean.

Those are the overloaded functions.

        public void WriteBlock(TableBlock block) { }
        public void WriteBlock(TextBlock block) { }
        public void WriteBlock(ListBlock block) { }

And This is The function I want to implement.

        public void WriteBlocks(List<Block> blocks)
        {
            BlockWriter w = new BlockWriter();

            foreach (var block in blocks)
            {
                w.WriteBlock(block);
            }
        }

Note that I have no access on the Blocks classes.

like image 977
A.khaled Avatar asked Sep 18 '25 12:09

A.khaled


1 Answers

Yes, it is possible using the dynamic type which allows for this.

If you use:

        foreach (var block in blocks)
        {
            w.WriteBlock(block as dynamic);
        }

It should call the intended WriteBlock overload.

This is described in greater length in another question: https://stackoverflow.com/a/40618674/3195477

And also here: method overloading and dynamic keyword in C#.


Caveats:

I am not sure if there is any runtime penalty associated with this type of dynamic "cast".

Also whenever I see this pattern it makes me wonder if the class hierarchy could be improved. i.e., should whatever WriteBlock will do actually be moved inside the Block classes? That might be "more polymorphic". Also using dynamic could be a somewhat fragile approach, as you can add new Block derived types and forget to an an overloaded WriteBlock for them, which may cause an error. (This is more evidence that some of WriteBlock should be incorporated into the Block classes themselves).

For instance, add a virtual PrepareForWriting() to the base Block class, which returns a BlockWritable. Then you only need one WriteBlock(BlockWritable data) to do the writing work. BlockWritable could be a string, Json, XML, etc. This assumes you are able to modify the Block classes (which it seems you cannot).

like image 139
StayOnTarget Avatar answered Sep 20 '25 02:09

StayOnTarget