As a warning, techniques like the one following won't work either...
generic <typename T> public interface class ICollection { void Add(T item); };
class Immutable { bool IsReadOnly() { return true; } };
class Mutable { bool IsReadOnly() { return false; } };
template <typename T, typename M>
ref class MyCollection : public ICollection<T>
{
typedef M MutType;
public:
void Add(T item) {
if (MutType::IsReadOnly() throw gcnew NotSupportedException();
internal.Add(item);
}
System::Collections::Generic::List<T> internal;
};
public ref class Element { ... };
public ref class FactoryClass
{
public:
static ICollection<Element^> CreateMutableCollection() { return gcnew MyCollection<Element^, Mutable>(); }
static ICollection<Element^> CreateImmutableCollection() { return gcnew MyCollection<Element^, Immutable>(); }
};
Compiling the above, and calling CreateMutableCollection and CreateImmutableCollection from another assembly, always (in my case - I'm not sure the heuristics the compiler used) chose MyCollection<Element^, Mutable>, so it appears that the compiler only instantiates the template once, and uses that instantiation for all references. Shame, as this would be a useful combination of the two techniques, allowing (internally) manufacturing implementations of a generic interface using templates.