如果隐藏的目的是使用新的关键字
我有下面的代码片段生成“使用新的关键字,如果隐藏是有意的”警告在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 { ... } }
这几乎是避免这种警告的唯一技巧,因为编译器暗示你可能隐藏了而没有意识到自己正在做什么。