Question

I am currently trying to get deeper into the .NET framework. I ran across an error while I was wondering if I could create two CommandManagers:

Cannot create an instance of CommandManager because it has no public constructors.

Obviously it means: don't do it, and it might not even make sense to have two of them. Now I came across an other error before with the message:

Cannot create an instance of ... because it is sealed

The effect is the same in prohibiting but what is the difference. Why does one choose a class to have no public constructors vs making it sealed?

EDIT:

Sorry I was ill for a couple of days. Further I mixed two languages: VB and C#. I had two tabs open and overlooked that one was standing on C# and one on VB Code. One class was sealed the other seemed to be NonInheritable. I didn't realize that this is actually the same. Now the error messages make sens.

IronPython Code snippet:

commandManager = CommandManager()

fails with

Cannot create instances of CommandManager because it has no public constructors

while

class MyCommandManager(CommandManager):
    return super(MyCommandManager, self).__init__(*args, **kwargs)()

fails with:

cannot derive from System.Windows.Input.CommandManager because it is sealed

I was mislead by these errormessages and since my google and stackoverflow search returned no answer (naturally because CommandManager is always sealed in C# while always NonInheritable in VB) Further CommandManager seems to be both sealed and having no public constructor.

Was it helpful?

Solution

You seal a class to prevent it from being subclassed. You remove public constructors to prevent a class from being directly instantiated, usually as part of a singleton pattern.

You can, of course, combine both.

OTHER TIPS

Sealed means you cannot inherit from it. That's the difference here. You can still create an instance, but cannot inherit.

The sealed keyword has to do with whether the class can be used as a base class. You can absolutely instantiate a sealed class.

Sealed denotes a class from which subclasses cannot be derived; your second error would have to refer to the inability to create a specific subclassing attempt, not an attempt to create an instance of the sealed class itself.

The main reason for not declaring any public constructors for a class are to control the creation of its instances. This is done in the singleton pattern as noted. This might also be done for a factory pattern implementation. In my game engine I do it for various parsers of shared portions of definition files with multiple versions. Sometimes I make all constructors private; sometimes internal; and sometimes protected to provide different control mechanisms. In none of these cases am I actually enforcing a singleton pattern.

Here is an extract of this usage:

internal abstract class AbstractParser {
  protected TextReader              Reader    { get; set; }
  // etc.
}

internal abstract class MapParser : AbstractParser, IParser<IMapDefinition> {
  public abstract IMapDefinition Parse();
  protected internal MapParser(TextReader reader) : this() { 
    Reader = reader;
  }
  public IMapDefinition Parse(Func<MapHeader, string[], int[][],
    HexsideData[,], List<IHpsPlaceName>, int, IMapDefinition> factory
  ) {
    var header     = ParseMapHeader(1);
    var terrain    = ParseTerrain(header.Size);
    var elevations = ParseElevation(header.Size);
    var feature    = ParseFeatures( header.Size);
    var placeNames = ParsePlaceNames();

    return factory(header, terrain, elevations, feature, placeNames, MaxElevationLevel);
  }
  // etc.
}

internal class MapV1Parser : MapParser {
  internal MapV1Parser(TextReader reader) : base(reader) {}

  public override IMapDefinition Parse() {
    return base.Parse((h,t,e,f,p,xe) => (new MapDefinitionV1(h,t,e,f,p,xe)));
  }
}

internal class MapV2Parser : MapParser {
  private readonly Regex regexHeaderLine3;
  internal MapV2Parser(TextReader reader) : base(reader) {
    regexHeaderLine3  = new Regex(@"^([-]?[0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) ([0-1])$",
                                  RegexOptions.None);
  }
  public override IMapDefinition Parse() {
    return base.Parse((h,t,e,f,p,xe) => (new MapDefinitionV2(h,t,e,f,p,xe)));
  }
  protected override Line3 ParseHeaderLine3() {  
    /* Definition override for V3 */
  }
}

This infrastructure allows the selection of the appropriate MapParser after reading the first line as follows:

internal static IParser<IMapDefinition> GetMapParser(TextReader reader) {
  string line = reader.ReadLine();
  short version;
  if (!short.TryParse(line, out version))
    Utils.ThrowInvalidDataException("MapParser",1,"Header","Non-integer version number",null,line);

  switch(version) {
    case 1:   return new MapV1Parser(reader);
    case 2:   return new MapV2Parser(reader);
    default:  Utils.ThrowInvalidDataException("MapParser",1,"Header","Unknown version number",
                null,version);
              return null;
  }
}

Some inside data

  • the keyword static is actually sealed abstract class [ClassName]

Where abstract says it must be inherited to use.

Where sealed closes it from inherit, because we all know you cant inherit static

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top