Question

I have a slight problem in my code here I think is interesting:

foreach(ISceneNode node in (root as IGroupNode))
            {
                PreVisit(node);
                if (notFound == false)
                {
                    return node;
                }
                else
                    PostVisit(node);
            }

I'm trying to call the methods PreVisit and PostVisit on the ISceneNode object node, which is a parent class to other types of nodes. However, because this is "too general" of an object relationship, I am not allowed to call the methods:

//methods
void PreVisit(IDrawableNode drawable)
    {
        string targetName = drawable.Name;
        Boolean notFound = true;
        CompareToTarget(targetName, notFound, drawable);
    }

    void PreVisit(ITransformNode transform)
    {
        string targetName = transform.Name;
        Boolean notFound = true;
        CompareToTarget(targetName, notFound, transform);
    }

    void PreVisit(IStateNode state)
    {
        string targetName = state.Name;
        Boolean notFound = true;
        CompareToTarget(targetName, notFound, state);
    }

    void PreVisit(IGroupNode group)
    {
        string targetName = group.Name;
        Boolean notFound = true;
        CompareToTarget(targetName, notFound, group);
    }

The IGroupNode, IStateNode, etc derive from the ISceneNode... so why can't I call this overloaded method using just an ISceneNode? Is it because it doesn't know which method to select? How can I account for this in my code and workaround it?

Was it helpful?

Solution

When you call your method, the object is ISceneNode, as you did not define a PreVisit(ISceneNode), it will fail to find a suitable method.

The compiler will not be able to understand that you already defined a subcase for each subtype. One solution would be to cast it to check if your object implement one of the sub interfaces and call the method on the casted object.

Of course, this is not really a good solution to just write this in the middle of the rest of the code. As SLaks mention you should use a dispatch, like here, or using C# 4.0 keyword dynamic as shown here

Here is the example of the second link:

class Animal 
{ 
}

class Cat : Animal 
{ 
}

class Dog : Animal 
{ 
}

Here are the specialisations:

void ReactSpecialization(Animal me, Animal other) 
{ 
    Console.WriteLine("{0} is not interested in {1}.", me, other); 
}

void ReactSpecialization(Cat me, Dog other) 
{ 
    Console.WriteLine("Cat runs away from dog."); 
}

void ReactSpecialization(Dog me, Cat other) 
{ 
    Console.WriteLine("Dog chases cat."); 
}

Now this is how you define the double dispatch in C# 4.0 using dynamic:

void React(Animal me, Animal other) 
{ 
    ReactSpecialization(me as dynamic, other as dynamic); 
}

Then run

void Test() 
{ 
    Animal cat = new Cat(); 
    Animal dog = new Dog(); 

    React(cat, dog); 
    React(dog, cat); 
}

OTHER TIPS

C# dynamic does that nicely:

PreVisit((dynamic)node);

That select the appropriate method at runtime using C# semantics.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top