如何编写一个通用函数来调用具有特定类的通用函数?

时间:2018-03-23 12:27:57

标签: c# generics delegates

我的代码:

public class BaseParamsClass
{
    public BaseParamsClass(int pBaseParam = 0)
    {
        baseParam = pBaseParam;
    }

    public int baseParam;
}

public class Parent1ParamsClass : BaseParamsClass
{
    public Parent1ParamsClass(int pBaseParam = 0) : base(pBaseParam)
    {

    }

    public int parentParam1;
}

public class Parent2ParamsClass : BaseParamsClass
{
    public Parent2ParamsClass(int pBaseParam = 0) : base(pBaseParam)
    {

    }

    public int parentParam2;
}

public delegate void Parent1Callback(Parent1ParamsClass theParams);
public delegate void Parent2Callback(Parent2ParamsClass theParams);

private IEnumerator CoRFunction1(Parent1Callback parent1Callback)
{
    // This demonstrate few actions i do before the call
    yield return new WaitForSeconds(1);

    // Now i get the result, it can be 0-10, each one should activate different callback
    int result = 0;

    parent1Callback(new Parent1ParamsClass(0));
}

private IEnumerator CoRFunction2(Parent2Callback parent2Callback)
{
    // This demonstrate few actions i do before the call
    yield return new WaitForSeconds(1);

    // Now i get the result, it can be 0-10, each one should activate different callback
    int result = 0;

    // Need a generic way to do the next line:
    parent2Callback(new Parent2ParamsClass(0));
}

private IEnumerator CoRFunction2(Parent2Callback parent2Callback)
{
    // This demonstrate few actions i do before the call
    yield return new WaitForSeconds(1);

    // Now i get the result, it can be 0-10, each one should activate different callback
    int result = 0;

    // Need a generic way to do the next line:
    parent2Callback(new Parent2ParamsClass(0));
}

我需要的是一种在'// Need a ...'之后用更通用的东西替换行的方法,这就是最后两个函数应该是这样的:

private IEnumerator CoRFunction1(Parent1Callback parent1Callback)
{
    // This demonstrate few actions i do before the call
    yield return new WaitForSeconds(1);

    // Now i get the result, it can be 0-10, each one should activate different callback
    int result = 0;

    genericFunction<Parent1Callback>(Parent1ParamsClass);
}

private IEnumerator CoRFunction2(Parent2Callback parent2Callback)
{
    // This demonstrate few actions i do before the call
    yield return new WaitForSeconds(1);

    // Now i get the result, it can be 0-10, each one should activate different callback
    int result = 0;

    genericFunction<Parent2Callback>(Parent2ParamsClass);
}

如何创建'genericFunction'?

2 个答案:

答案 0 :(得分:1)

我评论说 - 目前还不太清楚你想要达到的目标,我怀疑你能以比你想要的更好的方式做到这一点......但是为了记录,我认为

更改基本参数类,以便您不依赖于构造函数来设置其内部字段,然后将一些泛型方法仅限制为基类型,因此您最终会遇到这种情况:

public class BaseParamsClass
{
    public virtual void SetParam(int pBaseParam)
    {
        baseParam = 0;
    }

    public int baseParam;
}

public class Parent1ParamsClass : BaseParamsClass
{
    public override void SetParam(int pBaseParam)
    {
        base.SetParam(pBaseParam);
        //do other stuff specific to this class...
    }
    public int parentParam1;
}

public class Parent2ParamsClass : BaseParamsClass
{
    public override void SetParam(int pBaseParam)
    {
        base.SetParam(pBaseParam);
        //do other stuff specific to this class...
    }

    public int parentParam2;
}


public delegate void GenericCallback<T>(T theParams) where T : BaseParamsClass, new();

private IEnumerator GenericCorFunction<T>(GenericCallback<T> callback) where T:BaseParamsClass, new()
{
    // This demonstrate few actions i do before the call
    yield return new WaitForSeconds(1);

    // Now i get the result, it can be 0-10, each one should activate different callback
    int result = 0;

    //I assume you want result here.
    //Also note that you can't use the constructor to set the base param as at compile time
    //we're not sure which type will be being used.  There are ways around this but it's
    //probably clearer to use basic constructor then call the SetParam virtual/overridden method            
    var param = new T();
    param.SetParam(result);
    callback(param);
}
你可以用这样的东西:

var newEnumerator = GenericCorFunction<Parent2ParamsClass>(p =>
{
    //this is the callback function body.  This will only run when 
    //called at the end of the GenericCorFunction
    //Do things with p, which will be a PArent2ParamsClass object
    //with its baseParam field set to whatever result was.
    if (p.baseParam == 3)
    {
        throw new NotImplementedException();
    }
});

//do stuff with newEnumerator...

答案 1 :(得分:1)

另一种方法可能是使用Activator.CreateInstance。这将允许您绕过new()限制并使用已编写的构造函数:

public delegate void ParentCallback<T>(T theParams) where T : BaseParamsClass;

private void CoRFunction<T>(ParentCallback<T> parentCallback) where T : BaseParamsClass
{    
    // Now i get the result, it can be 0-10, each one should activate different callback
    int result = 0;

    parentCallback((T)Activator.CreateInstance(typeof(T), 11));
}

(我将其改为无效以使其对我来说是可测试的)

这是TestCode和我用来测试它的调用:

public void Call_1(Parent1ParamsClass par1)
{
    Console.WriteLine("CALL 1 baseParam: " + par1.baseParam);
}

public void Call_2(Parent2ParamsClass par2)
{
    Console.WriteLine("CALL 2 baseParam: " + par2.baseParam);
}

呼叫:

CoRFunction<Parent1ParamsClass>(Call_1);
CoRFunction<Parent2ParamsClass>(Call_2);

输出:

  

CALL 1 baseParam:11
  CALL 2 baseParam:11