I am trying to provide an interface to an abstract generic base class. I want to have a method exposed on the interface that consumes the generic type, but whose implementation is ultimately handled by the classes that inherit from my abstract generic base.
However I don't want the subclasses to have to downcast to work with the generic type (as they already know what the type should be).
Here is a simple version of the only way I can see to get it to work at the moment.
public interface IFoo
{
void Process(Bar_base bar);
}
public abstract class FooBase<T> : IFoo
where T : Bar_base
{
abstract void Process(T bar);
// Explicit IFoo Implementation
void IFoo.Process(Bar_base bar)
{
if (bar == null) throw new ArgumentNullException();
// Downcast here in base class (less for subclasses to worry about)
T downcasted_bar = bar as T;
if (downcasted_bar == null)
{
throw new InvalidOperationException(
string.Format("Expected type '{0}', not type '{1}'",
T.ToString(), bar.GetType().ToString());
}
//Process downcasted object.
Process(downcasted_bar);
}
}
Then subclasses of FooBase would look like this...
public class Foo_impl1 : FooBase<Bar_impl1>
{
void override Process(Bar_impl1 bar)
{
//No need to downcast here!
}
}
Obviously this won't provide me compile time Type Checking, but I think it will get the job done...
Questions:
1. Will this function as I think it will?
2. Is this the best way to do this?
3. What are the issues with doing it this way?
4. Can you suggest a different approach?
Thanks!
Edit: In Response to many answers, It is a requirement that IFoo is not Generic. I need to be able to manipulate a collection of IFoo objects regardless of the generic Types they use.
Edit: In an effort to clarify the reasoning for this...
Bar_base contains a reference to type IFoo. And must call the process method to validate the data it contains. Think of IFoo as an object that contains validation logic for the Bar_base derived objects. When the validity of Bar_base object is questioned, it calls Process on its IFoo reference to validate itself.
The reason IFoo can't be generic is that I need to be able to reference a collection of IFoo independent of the Bar_base classes.
I am going to try the approach of having two interfaces a Generic one that contains the Process method, and non-generic one that doesn't.
In the case where IFoo cannot be generic, it's very typical in a case like this to have two interfaces, IFoo<T>
and IFoo, where IFoo uses the most base class supported. Think IEnumerable<T>
and IEnumerable. The non-generic version is usually hidden as an interface overload, so it only comes into play when accessing the class via the non-generic interface.
Given your constraint that T is of type Bar_base, and (in your example) only using T for Process(T bar), I'm not sure why you're using generics at all. If
abstract Process(Bar_base bar)
is all you need, then that should be sufficient for class overriding with
void override Process(Bar_impl1 bar)
and your abstract class Bar_base is a sufficient type constraint.
Unless I'm missing something....
Another useful trick is to provide both generic and non-generic interface definitions, where the non-generic provides non-generic access methods and properties, and the generic interface provides only the additional methods and/or properties that requires a generic type. Clients can specify either interface, depending on whether they're in a position to share the generic type.
interface IFoo
{
...
}
interface IFoo<T> : IFoo where T : Bar_base
{
...
}
But I'm not sure that this would satisfy your needs in this case.
You could just make IFoo generic:
public interface IFoo<T> where T : Bar_base
{
void Process(T bar);
}
Any reason you don't just use a generic interface:-
public interface IFoo<T>
where T:Bar_base
{
void Process(T bar);
}
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.