-1

我目前正在尝试更深入地了解 .NET 框架。当我想知道是否可以创建两个 CommandManager 时遇到了一个错误:

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

显然它的意思是:不要这样做,拥有两个可能甚至没有意义。现在我在消息之前遇到了另一个错误:

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

禁止的效果是一样的,但有什么区别。为什么选择一个没有公共构造函数的类而不是使其密封?

编辑:

对不起,我病了几天。此外,我混合了两种语言:VB 和 C#。我打开了两个选项卡,但忽略了一个在 C# 上,一个在 VB 代码上。一类被密封,另一类似乎是不可继承的。我没有意识到这实际上是一样的。现在错误消息是有道理的。

IronPython 代码片段:

commandManager = CommandManager()

失败了

Cannot create instances of CommandManager because it has no public constructors

尽管

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

失败:

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

我被这些错误消息误导了,因为我的 google 和 stackoverflow 搜索没有返回任何答案(自然是因为 CommandManager 总是在 C# 中密封,而在 VB 中总是 NonInheritable)进一步的 CommandManager 似乎是密封的并且没有公共构造函数。

4

5 回答 5

12

您密封一个类以防止它被子类化。您删除公共构造函数以防止直接实例化类,通常作为单例模式的一部分。

当然,您可以将两者结合起来。

于 2013-04-26T20:12:45.853 回答
2

Sealed意味着你不能继承它。这就是这里的区别。您仍然可以创建实例,但不能继承。

于 2013-04-26T20:12:36.703 回答
1

关键字与该类sealed是否可以用作基类有关。您绝对可以实例化密封类。

于 2013-04-26T20:12:37.983 回答
0

Sealed表示不能派生子类的类;您的第二个错误必须是指无法创建特定的子类化尝试,而不是尝试创建密封类本身的实例。

不为类声明任何公共构造函数的主要原因是为了控制其实例的创建。如前所述,这是在单例模式中完成的。这也可以用于工厂模式实现。在我的游戏引擎中,我为具有多个版本的定义文件的共享部分的各种解析器执行此操作。有时我将所有构造函数设为私有;有时是内部的;有时受保护以提供不同的控制机制。在这些情况下,我实际上都没有强制执行单例模式。

这是此用法的摘录:

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 */
  }
}

此基础结构允许在读取第一行后选择适当的 MapParser,如下所示:

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;
  }
}
于 2013-04-26T20:21:19.963 回答
-1

一些内部数据

  • 关键字static实际上是sealed abstract class [ClassName]

哪里abstract说必须继承才能使用。

在哪里sealed关闭它从继承,因为我们都知道你不能继承static

于 2013-04-26T20:24:00.577 回答