C# 如果打算隐藏,请使用新关键字

C# 如果打算隐藏,请使用新关键字,c#,inheritance,warnings,new-operator,C#,Inheritance,Warnings,New Operator,我有以下代码片段,它在VS2008中生成了“如果打算隐藏,请使用新关键字”警告: public double Foo(double param) { return base.Foo(param); } 基类中的Foo()。也就是说,包装器类将不用于任何其他用途。所以我有一个问题:这是公认的做法吗? 返回到新建警告为什么我必须在这种情况下新建覆盖函数?新的只会让您清楚地知道您正在践踏现有的方法。由于现有的代码是受保护的,所以这没什么大不了的-您可以安全地添加新的来阻止它呻吟 当你的方法做了

我有以下代码片段,它在VS2008中生成了“如果打算隐藏,请使用新关键字”警告:

public double Foo(double param)
{
   return base.Foo(param);
}
基类中的
Foo()。也就是说,包装器类将不用于任何其他用途。所以我有一个问题:这是公认的做法吗?


返回到
新建
警告为什么我必须在这种情况下新建覆盖函数?

新的
只会让您清楚地知道您正在践踏现有的方法。由于现有的代码是受保护的,所以这没什么大不了的-您可以安全地添加新的
来阻止它呻吟

当你的方法做了一些不同的事情时,差异就来了;任何引用派生类并调用
Foo()
的变量都会与引用基类并调用
Foo()

这显然会对任何已知
SomeDerived
并调用
Foo()
的现有代码产生影响,也就是说,它现在运行的是一种完全不同的方法


另外,请注意,您可以将其标记为“受保护的内部”
,并使用
[InternalsVisibleTo]
提供对单元测试的访问(这是
[InternalsVisibleTo]最常用的用法)
;那么您的单元测试可以直接访问它,而无需派生类。

您正在更改可见性,而不需要名称。调用您的函数TestFoo,它就会工作。是的,出于这个原因,IMHO可以接受子类。

关键是您没有重写该方法。您正在隐藏它。如果您正在重写它,您需要e
override
关键字(此时,除非它是虚拟的,否则编译器会抱怨,因为您无法重写非虚拟方法)

您可以使用
new
关键字告诉编译器和任何阅读代码的人,“没关系,我知道这只是隐藏基本方法,而不是重写它——这就是我的本意。”


坦白地说,我认为隐藏方法很少是一个好主意——我会使用不同的方法名称,就像克雷格建议的那样——但这是一个不同的讨论。

你总会发现一些棘手的情况,新的
关键字可以用来隐藏,而大多数时候可以避免

但是,最近我确实需要这个关键字,主要是因为该语言缺少一些其他适当的synthax功能来完成现有的访问器,例如:

如果你考虑一个过时的类:

KeyedCollection<TKey, TItem>
同时具有
{get;set;}
,由于继承了
ICollection
Collection
,它们当然是必需的,但是只有一个
{get;}
可以通过它们的键访问项(我对这种设计有一些猜测,原因很多,因此请注意,我选择了
KeyedCollection)
仅用于插图)

无论如何,密钥访问只有一个getter:

TItem this[TKey key] { get; }
但是如果我想添加
{set;}
支持,从技术上讲,这并不是那么愚蠢,特别是如果你继续从以前的属性定义进行推理,它只是一种方法……唯一的方法是显式实现另一个虚拟接口,但当你想隐式实现时,你必须提出
新的
关键字,我隐藏了访问器定义,例如使用get;base定义,只需添加一个填充了一些个人内容的集合,即可使其正常工作

我认为对于这个非常具体的场景,这个关键字非常适用,特别是对于没有带到
{get;}
部分的上下文

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

这几乎是避免此类警告的唯一诀窍,因为编译器建议您可能在未意识到自己在做什么的情况下隐藏起来。

基类是否有构造函数?@Tom:这与构造函数无关。另请参阅此问题:有关类似实践的讨论
TItem this[TKey key] { get; }
  public new TItem this[TKey key]
  { 
      get { return base... }
      set { ... }
  }