我有些话要说
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;
}
}
处理方法的工作方式很丑:
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)
而不是Process(value, fakeValue)
或Process<SomeType>(value)
?
答案 0 :(得分:0)
将接口添加到基类。
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 */);
答案 1 :(得分:0)
public interface IGenericDoSomething
{
void DoSomethingWithDefault();
}
public class GenericDerived<T> : BaseClass, IGenericDoSomething where T : struct
{
public T data;
public void DoSomething<X>(X someParameter) => Console.WriteLine(someParameter);
void IGenericDoSomething.DoSomethingWithDefault() => DoSomething(default(T));
}
public void Process<T>(T someObject) where T : BaseClass {
switch (someObject)
{
case SimpleDerivedA a:
a.DoSomething();
break;
case SimpleDerivedB b:
b.DoSomething();
break;
case IGenericDoSomething g:
g.DoSomethingWithDefault();
break;
}
}
答案 2 :(得分:0)
对于类型为Process
的对象,应使用GenericDerived
函数的重载,而不是尝试在一个函数中处理所有内容。
void Process<T>(T someObject) where T : BaseClass {
switch (someObject)
{
case SimpleDerivedA a:
a.DoSomething();
break;
case SimpleDerivedB b:
b.DoSomething();
break;
}
}
void Process<X>(GenericDerived<X> g) where X : struct {
X obj = new X();
g.DoSomething(obj);
}
您可以这样称呼它。
var a = new SimpleDerivedA();
var b = new SimpleDerivedB();
var g = new GenericDerived<Vector3>();
Process(a);
Process(b);
Process(g);
还可以考虑为可以DoSomething
的对象引入接口,或为BaseClass
添加虚拟方法,因此您不必为了在不同对象上调用相同方法而进行类型切换。这可能无法实现,因为某些派生类中有一个参数,而其他类中没有。