如果隐藏的目的是使用新的关键字

我有下面的代码片段生成“使用新的关键字,如果隐藏是有意的”警告在VS2008中:

public double Foo(double param) { return base.Foo(param); } 

基类中的Foo()函数是受保护的,我想将它暴露给一个unit testing,只是为了unit testing的目的而将它放在包装类中。 即包装类将不会被用于其他任何事情。 所以我有一个问题是: 被接受的做法吗?

回到new警告。 为什么我必须在这种情况下新的重写function?

new只是很明显,你知道你正在跺脚现有的方法。 既然现有的代码是protected ,那就不是什么大事了 – 你可以安全地添加new来阻止它的呻吟。

当你的方法做了一些不同的事情时,差别就来了 任何引用派生类并调用Foo()variables都会做一些与引用类并调用Foo()相同的东西(即使是相同的对象Foo()

 SomeDerived obj = new SomeDerived(); obj.Foo(); // runs the new code SomeBase objBase = obj; // still the same object objBase.Foo(); // runs the old code 

这显然会对已知的SomeDerived和调用Foo()代码产生影响 – 也就是说,它现在正在运行一个完全不同的方法。

此外,请注意,您可以将其标记为protected internal ,并使用[InternalsVisibleTo]提供对您的unit testing的访问权限(这是[InternalsVisibleTo]的最常见用法;然后您的unit testing可以直接访问它,而无需派生类。

关键是你并不是压倒一切的方法。 你藏起来了 如果你重写它,你需要override关键字(在这一点上,除非它是虚拟的,编译器会抱怨,因为你不能覆盖非虚拟方法)。

你可以使用new关键字来告诉编译器和任何读取代码的人:“没关系,我知道这只是隐藏了基本方法而不是覆盖它 – 这就是我的意思。

坦率地说,我认为隐藏方法并不是一个好主意 – 我会用一个不同的方法名称,比如Craig所build议的 – 但这是一个不同的讨论。

你正在改变没有名字的可见性。 调用你的函数TestFoo,它会工作。 是的,恕我直言,这是可以接受的,因为这个原因。

你总是会发现一些棘手的情况, new关键字可以用来隐藏,而大部分时间都可以避免。

然而,最近我真的需要这个关键字,主要是因为语言缺乏一些其他合适的synthaxfunction来完成一个现有的访问者,例如:

如果你考虑一个老式的类如:

 KeyedCollection<TKey, TItem> 

你会注意到用于处理物品槽索引的accesor是:

 TItem this[Int32 index] { get; set; } 

既有{ get; set; } { get; set; } { get; set; }由于inheritance有关ICollection<T>Collection<T> ,所以它们当然是强制性的,但是只有一个{ get; } { get; }通过他们的钥匙来获取物品(我对这个devise有一些猜测,并且有很多原因,所以请注意,我拿起KeyedCollection<TKey, TItem>)仅仅是为了图示的目的)。

无论如何,所以只有一个获取钥匙访问:

 TItem this[TKey key] { get; } 

但是如果我想添加{ set; } { set; }技术上说,这并不是愚蠢的,特别是如果你继续从前面定义的propery的推理,这只是一个方法…唯一的方法是明确地实现另一个虚拟接口,但是当你想隐含你必须来与new关键字,我隐藏的访问者的定义,保持得到; 基本的定义,只是添加一些塞满了一些个人的东西,使其工作。

我认为对于这个非常具体的情况,这个关键字是完全适用的,特别是关于没有被带到{ get; } { get; }部分。

  public new TItem this[TKey key] { get { return base... } set { ... } } 

这几乎是避免这种警告的唯一技巧,因为编译器暗示你可能隐藏了而没有意识到自己正在做什么。