以下代码是否应发出警告?
class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public static void Do() { /*...*/ } /*...*/ }
它给出了:
“警告CS0108:'Bar.Do()'隐藏继承的成员'Foo.Do()'。如果想要隐藏,请使用new关键字。”
如果我对代码进行了更改:
class Foo { public static void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public void Do() { /*...*/ } /*...*/ }
我得到同样的警告。
但是,如果我做出以下更改,警告就会消失。
class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { new public static void Do() { /*...*/ } /*...*/ }
让我做出进一步的改变:
class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo {
new public static void Do()
{ new Bar().Do();/*...*/ } /*...*/
}
这不编译:
“错误CS0176:无法使用实例引用访问成员'Bar.Do()';而是使用类型名称限定它。”
因此,我无法通过静态方法的实例引用访问我继承的方法!
它背后的逻辑是什么?或者我在某个地方打错了?
当我尝试为从'Form'派生的表单定义一个静态方法'Show'时,我遇到了这个。
答案 0 :(得分:5)
您认为该错误在哪里?有警告的事实是绝对正确的。从C#3.0规范,第10.3.4节:
类成员声明是 允许宣布成员 同名或签名作为继承 会员。当这种情况发生时,派生出来 据说集体成员隐藏基地 班级成员。隐藏遗传 成员不被视为错误,但是 它确实会导致编译器发出一个 警告。要压制警告, 派生类的声明 成员可以包含一个新的修饰符 表明派生成员是 旨在隐藏基础成员。
您的方法调用失败的事实是更微妙的,但它基本上是因为成员查找算法选择静态方法,然后使用7.5.5.1节的这一部分:
最佳选择的最终验证 方法执行:
方法是 在方法的上下文中验证 group:如果最好的方法是静态的 方法,方法组必须具备 由一个简单的名字或一个 成员访问类型。如果 最好的方法是实例方法, 方法组必须由a产生 简单名称,成员访问通过 变量或值,或基本访问。 如果这些要求都不是 如果是,则发生编译时错误。
答案 1 :(得分:2)
不,这很有道理。这按预期工作:
using System;
using System.Collections.Generic;
class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo {
new public static void Do()
{ ((Foo)new Bar()).Do();/*...*/ } /*...*/
}
那是因为编译器假定您有一个Bar类型,然后找到静态成员。通过将它转换为Foo(它是免费的btw。),你可以在foo()的元数据中查找它,一切都很好。
答案 2 :(得分:2)
试试这个:
new public static void Do()
{
((Foo)new Bar()).Do();
}
答案 3 :(得分:1)
你应该可以通过调用base.Do()而不是Bar()调用它.Do()
答案 4 :(得分:0)
在最终的代码示例中,Bar.Do()声明中的new关键字表示您打算隐藏Foo.Do()。
答案 5 :(得分:0)
出于好奇,你为什么要这样做?看起来你可能错误地解决了你的解决方案。
上面的代码似乎正常工作,编译器消息告诉你问题是什么。