首页 > 解决方案 > 具有嵌套泛型类型的方法

问题描述

我有一些类似的东西:

public class BaseClass
{

}

public class SimpleDerivedA : BaseClass
{
    public void DoSomething() => Expression.Empty();        
}

public class SimpleDerivedB : BaseClass
{
    public void DoSomething() => Expression.Empty();          
}

public class GenericDerived<T> : BaseClass where T : struct
{
    public T data;
    public void DoSomething<T>(T someParameter) => Expression.Empty();        
}

public void Process<T, X>(T someObject, X someValue = default) where T : BaseClass where X : struct
{
    switch (someObject)
    {
        case SimpleDerivedA a:
            a.DoSomething();
            break;
        case SimpleDerivedB b:
            b.DoSomething();
            break;
        case GenericDerived<X> g:
            X obj = new X();
            g.DoSomething(obj);
            break;
    }

}

Process 方法以一种丑陋的方式工作:

    SimpleDerivedA a = new SimpleDerivedA();
    SimpleDerivedB b = new SimpleDerivedB();
    GenericDerived<Vector3> g = new GenericDerived<Vector3>();

    Process(a, new int()); //second parameter is fake, just to be able to 
    call the method
    Process(b, new int()); //second parameter is fake, just to be able to 
    call the method
    Process(g, new Vector3());//second parameter is fake, just to be able to 
    call the method

理想情况下,我应该能够调用 Process(a), Process(b), Process(g)

就像是:

public void Process<T>(T someObject)  where T: BaseClass where X: struct
    {
        switch (someObject)
        {
            case SimpleDerivedA a:
                a.DoSomething();
                break;
            case SimpleDerivedB b:
                b.DoSomething();
                break;
            case GenericDerived<X> g:
                var obj = new X();
                g.DoSomething(obj);
                break;
        }

    }

或者:

public void Process<T<X>>(T someObject) where T : BaseClass where X : struct
    {
        switch (someObject)
        {
            case SimpleDerivedA a:
                a.DoSomething();
                break;
            case SimpleDerivedB b:
                b.DoSomething();
                break;
            case GenericDerived<X> g:
                var obj = new X();
                g.DoSomething(obj);
                break;
        }

    }

这显然不编译。我需要在 API 中使用它,并且在GenericDerived<T>有人使用它之前不会知道它的类型。

这里的问题是如何定义方法 Process 以便我可以使用三个派生类中的任何一个的实例作为参数,但只使用一个参数调用它,例如Process(value)notProcess(value, fakeValue)Process<SomeType>(value)

标签: c#generics

解决方案


向基类添加接口。

interface IProcessable
{
    void DoSomething(params object [] args);
}

public abstract class BaseClass : IProcessable
{
    public abstract void DoSomething(params object[] args);
}

public class GenericDerived<T> : BaseClass where T : struct
{
    public T data;
    public override void DoSomething(params object[] args)
    {
        // optionally you can pass as many arguments as you like
        data = (T)args.First();
    }
}

然后你可以将你的对象传递给这样的方法。

public static void Process(IProcessable obj, params object[] args)
{
    obj.DoSomething(args);
}

然后像这样从你需要的地方调用它

var a =  new SimpleDerivedA();
var b = new SimpleDerivedB();
var c = new GenericDerived<T>();
Process(a);
Process(b);
Process(c, obj /* your struct T */);

推荐阅读