我想在我的派生类中隐藏基本公共属性(数据成员):
class Program
{
static void Main(string[] args)
{
b obj = new b();
obj.item1 = 4;// should show an error but it doent ???
}
}
class a
{
public int item1 {get; set;}
public int item2 { get; set; }
}
class b : a
{
new private int item1;
}
class c : a
{
}
Run Code Online (Sandbox Code Playgroud)
我有成员公开因为我希望成员在c类中继承,但是想要隐藏b类中的成员,我该怎么做?
我没有选择继承我想要在我的基类中的变量??? 多数民众赞成真的很糟糕,我认为ms应该为我们提供一个选项(可能是修改器)来执行此操作
编辑:
我自己找到了答案(我听到很多人告诉我这在c#中是不可能的,但你可以这样做)
我包含代码以防它有用
class Program
{
static void Main(string[] args)
{
b obj = new b();
obj.item1 = 4; // shows an error : )
}
}
class a
{
public int item1 { get; set; }
public int item2 { get; set; }
}
class b : a
{
new public static int item1
{
get;
private set;
}
}
Run Code Online (Sandbox Code Playgroud)
ICR*_*ICR 26
我将尝试用例子解释为什么这是一个坏主意,而不是使用神秘的术语.
您的建议是使用如下代码:
public class Base
{
public int Item1 { get; set; }
public int Item2 { get; set; }
}
public class WithHidden : Base
{
hide Item1; // Assuming some new feature "hide" in C#
}
public class WithoutHidden : Base { }
Run Code Online (Sandbox Code Playgroud)
这将使以下代码无效:
WithHidden a = new WithHidden();
a.Item1 = 10; // Invalid - cannot access property Item1
int i = a.Item1; // Invalid - cannot access property Item1
Run Code Online (Sandbox Code Playgroud)
这就是你想要的.但是,假设我们现在有以下代码:
Base withHidden = new WithHidden();
Base withoutHidden = new WithoutHidden();
SetItem1(withHidden);
SetItem1(withoutHidden);
public void SetItem1(Base base)
{
base.Item1 = 10;
}
Run Code Online (Sandbox Code Playgroud)
编译器不知道SetItem1中的参数库将是什么运行时类型,只是它至少是Base类型(或从Base派生的某种类型,但它无法分辨哪个 - 它可能很明显看着代码片段,但更复杂的场景使其几乎不可能).
因此,在很大比例的情况下,编译器不会给出编译器错误,即Item1实际上是不可访问的.这样就可以进行运行时检查.当您尝试在实际上为WithHidden类型的对象上设置Item1时,它将抛出异常.
现在访问任何成员,任何非密封类(大多数属性)上的任何属性都可能抛出异常,因为它实际上是隐藏成员的派生类.暴露任何非密封类型的任何库在访问任何成员时都必须编写防御性代码,因为有人可能隐藏了它.
对此的潜在解决方案是编写该特征,使得只能隐藏声明自己可隐藏的成员.然后,编译器将禁止对该类型的变量(编译时)访问隐藏成员,并且还包括运行时检查,以便在将其转换为基类型并尝试从该类型(运行时)进行访问时抛出FieldAccessException. .
但即使C#开发人员确实为此功能付出了巨大的麻烦和代价(请记住,功能很昂贵,特别是在语言设计方面),仍然必须编写防御性代码以避免潜在的FieldAccessExceptions被抛出的问题,那么有什么优势呢?重组你的继承层次结构你获得了吗?使用新成员隐藏功能,将有大量潜在的地方可以让bug进入您的应用程序和库,从而增加开发和测试时间.
瓦迪姆的回答让我想起了MS在某些地方如何在框架中实现这一目标.一般策略是使用EditorBrowsable属性隐藏Intellisense中的成员.(注意,如果它在另一个程序集中,它只会隐藏它)虽然它不会阻止任何人使用该属性,并且如果它们转换为基本类型它们可以看到它(参见我之前的探索),它使得它更难被发现,因为它没有出现在Intellisense中并保持类的接口干净.
它应该谨慎,虽然可以使用,只有当像重组继承层次其他选项将使其成为很多更加复杂.这是最后的手段,而不是第一个想到的解决方案.
我唯一能想到的就是在a类中将item1虚拟化:
class a
{
public virtual int item1 { get; set; }
public int item2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后在类 b 中重写它,但在 getter 和 setter 中抛出异常。此外,如果在可视设计器中使用此属性,您可以使用Browsable 属性来不显示。
class b : a
{
[Browsable(false)]
public override int item1
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果使用接口而不是基类来定义属性,则可以显式实现该属性.需要对接口进行显式强制转换才能使用该属性.
public interface IMyInterface
{
string Name { get; set; }
}
public class MyClass : IMyInterface
{
string IMyInterface.Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
你可以在这里找到更多.