I have the following situation:
// A public interface of some kind
public interface IMyInterface {
int Something { get; set; }
}
// An internal class that implements the public interface.
// Despite the internal/public mismatch, this works.
internal class MyInternalConcrete : IMyInterface {
public int Something { get; set; }
}
// A generic class with an interface-restricted type parameter.
// Note that the constraint on T uses the *public* interface.
// The instance is *never* exposed as a public, or even protected member.
public class MyClass<T> where T : IMyInterface, new() {
T myInterfaceInstance;
public MyClass() {
myInterfaceInstance = new T();
}
}
// Attempting to implement concrete class... Inconsistent Accessibility Error!
public class MySpecificClass : MyClass<MyInternalConcrete>
{
}
When trying to implement MySpecificClass, I get the error:
Inconsistent accessibility: base class 'App1.MyClass' is less accessible than class 'App1.MySpecificT'
Where it gets weird is that MyInternalConcrete, despite being internal, can still implement a public interface. And since it implements the interface, then it should be useable as a type parameter for MyClass – because T is constrained on the public interface and not the internal class.
I would understand it failing if MyClass exposed T, just as it would fail if we weren't using generics:
public class MyClass<T> where T : IMyInterface, new() {
T myInterfaceInstance;
public MyClass() {
myInterfaceInstance = new T();
}
// This will fail with an internal T - inconsistent accessibility!
public T Instance {
get { return myInterfaceInstance; }
}
}
And same as above, but without generics:
public class MyNonGenericClass {
MyInternalConcrete myInterfaceInstance;
public MyNonGenericClass() {
myInterfaceInstance = new MyInternalConcrete();
}
// This will fail - inconsistent accessibility!
// but removing it works, since the private instance is never exposed.
public MyInternalConcrete Instance {
get { return myInterfaceInstance; }
}
}
Is this a limitation of the C# generics or am I simply misunderstanding something fundamental about how generics work?
I also posted this thread on MSDN, but I'm being dismissed as not knowing what I'm talking about. Is my concern even valid?
Best Solution
This constraint you are facing makes sense for the following reason.
C# is strongly typed so...
To be able to reference the MySpecificClass outside the scope of the assembly it is defined in you must know its parameter types in order to generate a strong type reference to its instance; but an separate assembly than the internal definition does not know about MyInternalConcrete.
Thus the following wont work if in a separate assembly:
Here the separate assembly doesn't know of MyInternalConcrete, so how can you define a variable as such.