I have an internal class, an internal constructor won\'t allow it to be used in a generic collection so I changed it to public. What\'s the accessibility if you have a publi
A public class with an internal constructor can still be used by outside code, if you return an object of that class from a public function.
Outside code then has access to that object, but still can not create a new one.
Assembly 1:
public class Exclusive
{
internal Exclusive() {}
public void DoSomething() {}
}
public class Factory
{
public Exclusive GetExclusive() { return new Exclusive(); }
}
Assembly 2:
Factory MyFactory = new Factory();
Exclusive MyExclusive = MyFactory.GetExclusive(); // Object is created in Assembly 1
MyExclusive.DoSomething();
Exclusive MyExclusive = new Exclusive(); // Error: constructor is internal
Whereas an internal class can not be used outside the assembly at all:
Assembly 1:
internal class Exclusive
{
public Exclusive() {}
public void DoSomething() {}
}
public class Factory
{
public Exclusive GetExclusive() { return new Exclusive(); }
}
Assembly 2:
Factory MyFactory = new Factory();
Exclusive MyExclusive = MyFactory.GetExclusive(); // Error: class Exclusive not found
Having an internal or public constructor to an internal type would be equivalent in terms of visibility.
The two are essentially the same. One argument I've seen for distinguishing between them is that making your constructor internal
ensures the type will only ever be instantiated by types within the current assembly, even if it is later decided that the type itself should be public
instead of internal
. In other words you could decide to change the type's visibility without lifting restrictions on its instantiation.
Making the constructor public
has the opposite effect (obviously), and might be sensible if you want for it to be possible to instantiate the type anywhere it is visible.
Also, as you've already pointed out, one small difference is that if the constructor's internal
, the type cannot be used as a generic type argument for a generic type with a where T : new()
constraint, as this constraint requires for the constructor to be public
.
internal constructor are good when you don't want the client to create the instance. You'd usually want to do it if you want to control how the instance should be created.You will have to provide either a Factory to generate the class in another class within the same assembly to generate the instance internally and then expose as a property.
Another important distinction is that to access an internal
constructor using reflection, you need to specify binding flags in your call to Type.GetConstructor()
- the Type.GetConstructor(Type[])
overload will only return a public constructor:
using System;
internal class WithPublic
{
public WithPublic() { }
}
internal class WithInternal
{
internal WithInternal() { }
}
public class Program
{
public static void Main()
{
Console.WriteLine(typeof(WithPublic).GetConstructor(new Type[] { }) == null); //false
Console.WriteLine(typeof(WithInternal).GetConstructor(new Type[] { }) == null); //true
}
}
This might be important when you're using a library which utilizes the Type.GetConstructor(Type[])
overload, like Microsoft Unity.