0

I have c# application. I have 2 different classes (Step1.State and Step2.State) (they implement same interface called IMDP.IState) which represents application state in 2 different steps of execution of my application. I have 2 overloaded methods to update application state.

I have following code in one of my method:

Step1.State s1s = null;
Step2.State s2s = null;

Then I am casting current state depending on its type. currentState is instance of implemented interface which is received as parameter. First I am storing it in a dynamic type.

  //currentState is instance of IMDP.IState interface which is 
  //implemented by the two states

    dynamic curState=currentState;  

            if(curState is Step1.State)
            {
                s1s = (Step1.State)currentState;
                curState = s1s;

            }
            else if (curState is Step2.State)
            {
                s2as = (Step2.State)currentState;
                curState = s2s;

            }

Then I am calling my overloaded method inside the same method.

  currentState = myAgent.UserStateUpdate(prevAction, curState, e.Result);

UserStateUpdate method has 2 overloaded versions. First one gets Step1.State and second one gets Step2.State as differentiating parameter.. Like following;

IMDP.IState UserStateUpdate(IMDP.IAction act, Step1.State st, RecogResult rr)
IMDP.IState UserStateUpdate(Step2.Abuse.Action act, Step2.State st, RecogResult rr)

Application calls correct method for Step1.State but when application move to Step2 which uses Step2.State for state representation. It throws the following exception. Note, when i check what is stored in curState (typed dynamic) before calling the overloaded method, I am seeing a correct state which is typed Step2.State.

"The best overloaded method match for 'BI4A.Agent.Agent.UserStateUpdate(BI4A.IMDP.IAction, BI4A.Step1.State, System.Speech.Recognition.RecognitionResult)' has some invalid arguments"

Which basically states that the system tries to call overloaded method which accept Step1.State instead of Step2.State. I could not figure out, how to make it call the right method. Thanks for any help.

alan turing
  • 463
  • 4
  • 20

1 Answers1

1

Alan,

The problem is not with the State parameter. I have verified this with the code given below:

class Program
{
    interface IState
    {
    }

    class State1 : IState
    {
    }

    class State2 : IState
    {
    }

    private static void UpdateState(State1 s1)
    {
        Console.WriteLine("State1 Updated.");
    }

    private static void UpdateState(State2 s1)
    {
        Console.WriteLine("State2 Updated.");
    }

    static void Main(string[] args)
    {
        var random = new Random(123456);
        var i = 10;

        while (i-- > 0)
        {
            var n = random.Next();

            dynamic curStep = (n % 2) == 0 ? (dynamic)new State1() : new State2();

            UpdateState(curStep);
        }

        Console.ReadKey();
    }
}

However, the problem seems to be because of mismatch of types in the first parameter. i.e IMDP.IAction and Step2.Abuse.Action. I got the same error when i modified the above code with action parameter. The modified code is given below:

class Program
{
    interface IState
    {
    }

    class State1 : IState
    {
    }

    class State2 : IState
    {
    }

    interface IAction
    {
    }

    class SomeAction : IAction
    {
    }

    private static void UpdateState(IAction act, State1 s1)
    {
        Console.WriteLine("State1 IAction Updated.");
    }

    private static void UpdateState(SomeAction act, State2 s1)
    {
        Console.WriteLine("State2 SomeAction Updated.");
    }

    static void Main(string[] args)
    {
        var random = new Random(123456);
        var i = 10;
        IAction act = new SomeAction();

        while (i-- > 0)
        {
            var n = random.Next();

            dynamic curStep = (n % 2) == 0 ? (dynamic)new State1() : new State2();

            UpdateState(act, curStep);
        }

        Console.ReadKey();
    }
}

After digging online, i came across the below link which mentions that it is a know bug. https://connect.microsoft.com/VisualStudio/feedback/details/597276/dynamic-runtime-fails-to-find-iset-t-contains-during-runtime

Also, refer stackoverflow entry Passing a dynamic parameter throws RuntimeBinderException when calling Method from Inherited interface

Proposed solution: I suggest that you change the type of action parameter of second method from Step2.Abuse.Action to IMDP.IAction. I know that this is not an elegant solution but it works. To make sure you allow only objects of type Step2.Abuse.Action, you can check the object type and throw and exception like this:

if (!(act is Step2.Abuse.Action))
    throw new Exception('Invalid Action Type.');

I hope this helps.

Community
  • 1
  • 1
Vinod Kumar Y S
  • 628
  • 3
  • 9