C# 如果打算隐藏,请使用 new 关键字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/451035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use new keyword if hiding was intended
提问by Guy
I have the following snippet of code that's generating the "Use new keyword if hiding was intended" warning in VS2008:
我有以下代码片段在 VS2008 中生成“如果有意隐藏则使用新关键字”警告:
public double Foo(double param)
{
return base.Foo(param);
}
The Foo()
function in the base class is protected and I want to expose it to a unit test by putting it in wrapper class solely for the purpose of unit testing. I.e. the wrapper class will not be used for anything else. So one question I have is: is this accepted practice?
Foo()
基类中的函数是受保护的,我想通过将它放在包装类中来将它暴露给单元测试,仅用于单元测试。即包装类不会用于其他任何事情。所以我的一个问题是:这是公认的做法吗?
Back to the new
warning. Why would I have to new the overriding function in this scenario?
回到new
警告。为什么我必须在这种情况下新建覆盖函数?
采纳答案by Marc Gravell
The new
just makes it absolutely clear that you know you are stomping over an existing method. Since the existing code was protected
, it isn't as big a deal - you can safely add the new
to stop it moaning.
The new
just 清楚地表明你知道你正在践踏现有的方法。由于现有代码是protected
,所以没什么大不了的 - 您可以安全地添加new
来阻止它的呻吟。
The difference comes when your method does something different; any variable that references the derivedclass and calls Foo()
would do something different (even with the same object) as one that references the baseclass and calls Foo()
:
当你的方法做了不同的事情时,差异就出现了;任何引用派生类和调用的变量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
This could obviously have an impact on any existing code that knows about SomeDerived
and calls Foo()
- i.e. it is now running a completely different method.
这显然会对任何已知SomeDerived
和调用的现有代码产生影响Foo()
- 即它现在正在运行完全不同的方法。
Also, note that you could mark it protected internal
, and use [InternalsVisibleTo]
to provide access to your unit test (this is the most common use of [InternalsVisibleTo]
; then your unit-tests can access it directly without the derived class.
另外,请注意,您可以标记它protected internal
,并用于[InternalsVisibleTo]
提供对单元测试的访问(这是 ; 的最常见用法,[InternalsVisibleTo]
然后您的单元测试可以直接访问它而无需派生类。
回答by Craig Stuntz
You're changing the visibility without the name. Call your function TestFoo and it will work. Yes, IMHO it's acceptable to subclass for this reason.
您正在更改没有名称的可见性。调用您的函数 TestFoo 它将起作用。是的,恕我直言,出于这个原因子类化是可以接受的。
回答by Jon Skeet
The key is that you're notoverriding the method. You're hiding it. If you were overriding it, you'd need the override
keyword (at which point, unless it's virtual, the compiler would complain because you can'toverride a non-virtual method).
关键是您没有覆盖该方法。你在隐藏它。如果要覆盖它,则需要override
关键字(此时,除非它是虚拟的,否则编译器会抱怨,因为您无法覆盖非虚拟方法)。
You use the new
keyword to tell both the compiler and anyone reading the code, "It's okay, I know this is only hiding the base method and not overriding it - that's what I meant to do."
你使用new
关键字告诉编译器和任何阅读代码的人,“没关系,我知道这只是隐藏了基本方法而不是覆盖它——这就是我想要做的。”
Frankly I think it's rarely a good idea to hide methods - I'd use a different method name, like Craig suggested - but that's a different discussion.
坦率地说,我认为隐藏方法很少是一个好主意 - 我会使用不同的方法名称,就像 Craig 建议的那样 - 但这是一个不同的讨论。
回答by Perret
You'll always find some tricky situations where the new
keyword can be used for hiding while it can be avoided most of the times.
您总会发现一些棘手的情况,其中new
关键字可用于隐藏,而大多数情况下可以避免。
However, recently I really needed this keyword, mainly because the language lacks some other proper synthax features to complete an existing accessor for instance:
然而,最近我真的需要这个关键字,主要是因为该语言缺乏一些其他适当的 synthax 功能来完成现有的访问器,例如:
If you consider an old-fashioned class like:
如果你考虑一个老式的类,比如:
KeyedCollection<TKey, TItem>
You will notice that the accesor for acessing the items trough index is:
您会注意到访问项目槽索引的访问器是:
TItem this[Int32 index] { get; set; }
Has both { get; set; }
and they are of course mandatory due to the inheritance regarding ICollection<T>
and Collection<T>
, but there is only one { get; }
for acessing the items through their keys (I have some guesses about this design and there is plenty of reasons for that, so please note that I picked up the KeyedCollection<TKey, TItem>)
just for illustrations purposes).
既有{ get; set; }
他们当然强制性的因继承就ICollection<T>
和Collection<T>
,但只有一个{ get; }
通过自己的钥匙acessing的项目(我对这个设计的一些猜测,并有大量的原因是什么,所以请注意,我挑了KeyedCollection<TKey, TItem>)
只是为了说明目的)。
Anyway so there is only one getter for the keys access:
无论如何,密钥访问只有一个 getter:
TItem this[TKey key] { get; }
But what about if I want to add the { set; }
support, technically speaking it's not that stupid especially if you keep reasoning from the former definition of the propery, it's just a method... the only way is to implement explicitly another dummy interface but when you want to make implicit you have to come up with the new
keyword, I'm hiding the accessor definition, keeping the get; base definition and just add a set stuffed with some personal things to make it work.
但是如果我想添加{ set; }
支持怎么办,从技术上讲,这并不是那么愚蠢,尤其是如果您继续从属性的先前定义进行推理,它只是一种方法……唯一的方法是显式实现另一个虚拟接口,但是当您想要隐含你必须想出new
关键字,我隐藏了访问器定义,保留了get;基本定义,只需添加一个塞满一些个人物品的集合即可使其工作。
I think for this very specific scenario, this keyword is perfecly applicable, in particular in regards to a context where there is no brought to the { get; }
part.
我认为对于这个非常具体的场景,这个关键字是完全适用的,特别是在没有引入{ get; }
部分的上下文中。
public new TItem this[TKey key]
{
get { return base... }
set { ... }
}
That's pretty much the only trick to avoid this sort of warning cause the compiler is suggesting you that you're maybe hiding without realizing what you are doing.
这几乎是避免此类警告的唯一技巧,因为编译器会建议您可能隐藏起来而没有意识到自己在做什么。