I have something along the lines:
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 method works in an ugly way:
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
Ideally I should be able to call Process(a), Process(b), Process(g)
Something like:
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;
}
}
or:
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;
}
}
Which obviously don't compile. I need to use it inside an API and the type of GenericDerived<T>
won't be known until someone will use it.
The question here is how can I define the method Process so I can use an instance of any of the three derived classes as a parameter but call it only with one parameter like Process(value)
not Process(value, fakeValue)
or Process<SomeType>(value)
?
Add interface to the base class.
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();
}
}
And then you can pass your object into method like this.
public static void Process(IProcessable obj, params object[] args)
{
obj.DoSomething(args);
}
Then call it from where ever you need like this
var a = new SimpleDerivedA();
var b = new SimpleDerivedB();
var c = new GenericDerived<T>();
Process(a);
Process(b);
Process(c, obj /* your struct T */);
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;
}
}
You should use an overload of your Process
function for objects of type GenericDerived
, instead of trying to handle everything in one function.
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);
}
You can then call it like this.
var a = new SimpleDerivedA();
var b = new SimpleDerivedB();
var g = new GenericDerived<Vector3>();
Process(a);
Process(b);
Process(g);
Also consider introducing an interface for objects that can DoSomething
, or add a virtual method to BaseClass
, so you don't have to type-switch just to call the same method on different objects. This might not be possible since there's a parameter in some derived classes but not others.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.