public interface PipelineElement<in TIn, out TOut>
{
IEnumerable<TOut> Run(IEnumerable<TIn> input, Action<Error> errorReporter);
}
public interface Stage
{
}
public abstract class PipelineElementBase<TIn, TOut> : PipelineElement<object, object>,
PipelineElement<TIn, TOut> where TIn : Stage where TOut : Stage
{
IEnumerable<object> PipelineElement<object, object>.Run(IEnumerable<object> input, Action<Error> errorReporter)
{
return this.Run(input.Cast<TIn>(), errorReporter).Cast<object>();
}
public abstract IEnumerable<TOut> Run(IEnumerable<TIn> input, Action<Error> errorReporter);
}
object
doesn't implement Stage
, therefore neither TIn
nor TOut
could ever be object
, right? So why does the compiler think that PipelineElement<object, object>
and PipelineElement<TIn, TOut>
can become identical?
EDIT: Yes, it is perfectly possible to implement the same generic interface multiple times:
public interface MyInterface<A> { }
public class MyClass: MyInterface<string>, MyInterface<int> { }
From Compiler Error CS0695
'generic type' cannot implement both 'generic interface' and 'generic interface' because they may unify for some type parameter substitutions.
This error occurs when a generic class implements more than one parameterization of the same generic interface, and there exists a type parameter substitution which would make the two interfaces identical. To avoid this error, implement only one of the interfaces, or change the type parameters to avoid the conflict.
You can't implement both PipelineElementBase<TIn, TOut>
and PipelineElement<object, object>
interfaces to your abstract class.
As the error page said, you should;
From C# 5.0 Language Specification
13.4.2 Uniqueness of implemented interfaces
The interfaces implemented by a generic type declaration must remain unique for all possible constructed types. Without this rule, it would be impossible to determine the correct method to call for certain constructed types. For example, suppose a generic class declaration were permitted to be written as follows:
interface I<T>
{
void F();
}
class X<U,V>: I<U>, I<V>
{
void I<U>.F() {...}
void I<V>.F() {...}
}
Were this permitted, it would be impossible to determine which code to execute in the following case:
I<int> x = new X<int,int>();
x.F();
To determine if the interface list of a generic type declaration is valid, the following steps are performed:
Let L be the list of interfaces directly specified in a generic class, struct, or interface declaration C.
Add to L any base interfaces of the interfaces already in L.
Remove any duplicates from L.
If any possible constructed type created from C would, after type arguments are substituted into L, cause two interfaces in L to be identical, then the declaration of C is invalid. Constraint declarations are not considered when determining all possible constructed types.
In the class declaration
X
above, the interface list L consists ofI<U>
andI<V>
. The declaration is invalid because any constructed type withU
andV
being the same type would cause these two interfaces to be identical types.It is possible for interfaces specified at different inheritance levels to unify:
interface I<T> { void F(); } class Base<U>: I<U> { void I<U>.F() {…} } class Derived<U,V>: Base<U>, I<V> // Ok { void I<V>.F() {…} }
This code is valid even though
Derived<U,V>
implements bothI<U>
andI<V>
. The codeI<int> x = new Derived<int,int>(); x.F();
invokes the method in
Derived
, sinceDerived<int,int>
effectively re-implementsI<int>
(§13.4.6).
[Emphasis by the SO editor.]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With