The use of nested type parameters and recursion (C#)

旧时模样 提交于 2020-01-03 03:01:06

问题


I am trying to utilize nested parameter types which appears to be illegal. I would prefer to keep the recursive function below intact so that I do not have to duplicate logic. However my nested use of <Ttype> is making the CLR very upset (See Error listed in Code). The logic within MyMethod unavoidably creates delegates of both types Action<ClassA> and Action<ClassB>. Is there a way to alter the code below to accomplish my goal? Also what are the general restrictions concerning the use of type parameters (ie <Ttype>)? Perhaps the loss of type safety is why this type of code is prohibited?

ClassA->ClassB (inherets)

public void MyMethod<Ttype>(Action<Ttype> actionDelagate) where Ttype : ClassB
{
  // Recursive Call with Ttype=ClassA
  if (Only able create Class A delagate)
     MyMethod<ClassA>(v => doStuff)

  // Recursive Call with Ttype=ClassB
  if (Only able create Class B delagate)
     MyMethod<ClassB>(v => doStuff)

  // Utilize Delagate
  if (TypeOf(Ttype) == ClassA)
    actionDelagate(new Class A) // Expecting type "Ttype"
  else
    actionDelagate(new Class B) // Expecting type "Ttype"
}

Thanks, aidesigner


回答1:


The where clause you are using doesn't make sense. If you know the function takes ClassB, why would you not say myMethod<ClassB>(Action<ClassB> actionDelegate) ?

If you want to use some generic Ttype, you would need to say where Ttype : new() and then say new Ttype() when you call actionDelagate. That should do what you want.

public void MyMethod<Ttype>(Action<Ttype> actionDelagate) where Ttype : new()
{
    MyMethod<Ttype>(v => doStuff)

    actionDelagate(new Ttype()) // Expecting type "Ttype"
}



回答2:


I realized my attempt to abstract the problem made it hard to understand my restrictions. Below is the example again which is close to the implementation. The notes below should help, so you don't have to dig into the .NET classes.

  • Srgs* are .NET classes in namespace "System.Speech.Recognition.SrgsGrammar"
  • SrgsElement derives from SrgsItem
  • C# does not support "generics variance"! This means, counter to your intuition, the recursive calls cannot pass in "Action" even though SrgsItem "is a" SrgsElement.

I was able to solve my problem by creating a CreateSrgsNodes overload with Arg1 being Action. However this means maintaining the same code in both places which fails the smell test. If someone can improve upon this please proved a new answer.

    public void CreateSrgsNodes(Action<SrgsElement> addSrgsChild, CurrentNode)
    {
        foreach (GmlModel gmlModel in gmlModels)
        {

            if (<Pseudo Code: Is CurrentNode of type SrgsItem>)
            {
                var srgsOneOf = new SrgsOneOf();
                addSrgsChild(srgsOneOf);

                //Note: Arg1 is type SrgsElement
                CreateSrgsNodes(srgsOneOf.Add, CurrenNode.getChild);
            }


            if (<Pseudo Code: Is CurrentNode of type SrgsOneOf>)
            {
                var srgsOneOf = new SrgsOneOf();
                addSrgsChild(srgsOneOf);

                //Note: Arg1 is type SrgsItem (FAILS without an overload)
                CreateSrgsNodes(Action<SrgsItem>, CurrentNode))
                CreateSrgsNodes(srgsOneOf.Add,CurrenNode.getChild); created
            }
        }
    }


来源:https://stackoverflow.com/questions/6930340/the-use-of-nested-type-parameters-and-recursion-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!