【问题标题】:How to prevent illegal ICloneable<T> inheritance in C#?如何防止 C# 中的非法 ICloneable<T> 继承?
【发布时间】:2018-10-31 16:46:20
【问题描述】:

我有一个界面:

public interface ICloneable<out T>
    where T : ICloneable<T>
{
    T Clone();
}

应该接收实现此接口的类型(如下所示)。
我可以创建一个实现它的类:

public class Class : ICloneable<Class>
{
    public Class Clone() { return (Class)MemberwiseClone(); }
}

太棒了!

但是任何人都可以创建一个实现 ICloneable“错误”的类。
是否存在如下所示的防止继承的方法?(2 个示例)

public class Other : ICloneable<Class>
{
    public Class Clone() { return new Class(); }
}

public class Other : Class, ICloneable<Class>
{
    public Class Clone() { return (Other)MemberwiseClone(); }
}

并允许继承,如下所示? (任何来自 2 个示例)

public class Other : ICloneable<Other>
{
    public Other Clone() { return (Other)MemberwiseClone(); }
}

public class Other : Class, ICloneable<Other>
{
    public Other Clone() { return (Other)MemberwiseClone(); }
}

【问题讨论】:

  • 您只是在寻找sealed吗?
  • @leofun01这没有回答为什么。这回答了什么。
  • 所以您问是否有可能任何类都可以仅使用自身作为参数来实现接口?所以class Foo : ICloneable&lt;Bar&gt; 行不通,它必须 是class Foo : ICloneable&lt;Foo&gt;?
  • @leofun01 - 语言不支持这个。你只需要在实现你的类时小心。
  • 由于您的Class、Other 类和ICloneable 接口是公开的,因此任何开发人员都可以随心所欲地使用它。你可以告诉用户你的类应该做什么(描述接口),但你不能告诉他们如何实现它。此外,我个人仍然看不到此功能有任何可能的适用性。

标签: c# oop generics inheritance inheritance-prevention


【解决方案1】:

你不能重载一个类,所以:

public class Other : Class {}
public class Other : Class, IC<Other> {}

永远不会工作。

现在,我要拉一个 Jon Skeet 并展示你如何可以做到这一点,但随后劝阻你不要这样做。你可以这样做:

public class CloneableOther : Class, ICloneable<Other> {  }
public class Other : CloneableOther
{

}    

public class CloneableFoo : Class, ICloneable<Foo> { }
public class Foo : CloneableFoo
{

}

这段代码所做的是有效地从继承中删除泛型参数。除了Foo 仍然可以这样做:Foo : CloneableFoo, ICloneable&lt;Other&gt;,现在您必须为每个ICloneable 实例创建两个类。

这涉及到为什么你首先需要这个? Foo : IInterface&lt;Foo&gt; 是一种做法,但没有办法强制执行。你最好的选择是复制和粘贴,并确保类匹配。

也许另一种方法是在Class的构造函数中检查ICloneable的类型是否是类的类型,如果不是则抛出异常,这样可以排序感觉像是编译时错误,如果它在运行时做得足够早的话。

【讨论】:

  • 因为关键是要传入一个类型参数,但他想一起删除它,但我可能错了
  • 我认为他不想完全删除它。他想执行正确的。
  • 我意识到,这就是我删除那个位的原因。很奇怪,我觉得应该有办法做到这一点。
  • 你不能从 public class Other 继承 public class Other... 你得到一个错误。参见例如SharpLab
  • @xanatos 谢谢,忘了。我认为封装会更好。
猜你喜欢
  • 1970-01-01
  • 2011-01-12
  • 2015-03-17
  • 2010-10-31
  • 1970-01-01
  • 2017-12-22
  • 2011-04-15
  • 1970-01-01
相关资源
最近更新 更多