简体   繁体   English

为什么我的静态方法隐藏了我的实例方法?

[英]Why does my Static method hide my instance method?

Should the following code give a warning? 以下代码是否应该发出警告?

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public static void Do()  { /*...*/ } /*...*/ }

It gives: 它给:

"Warning CS0108: 'Bar.Do()' hides inherited member 'Foo.Do()'. Use the new keyword if hiding was intended." “警告CS0108:'Bar.Do()'隐藏继承的成员'Foo.Do()'。如果想要隐藏,请使用new关键字。”

If I make a change to the code: 如果我对代码进行了更改:

class Foo { public static void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public void Do()  { /*...*/ } /*...*/ }

I get the same warning. 我得到同样的警告。

If I make the following change, however, the warning goes away. 但是,如果我做出以下更改,警告就会消失。

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { new public static void Do() { /*...*/ } /*...*/ }

Let me make a further change: 让我做进一步的改变:

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { 
    new public static void Do() 
    { new Bar().Do();/*...*/ } /*...*/ 
}

This does not compile: 这不编译:

"Error CS0176: Member 'Bar.Do()' cannot be accessed with an instance reference; qualify it with a type name instead." “错误CS0176:无法使用实例引用访问成员'Bar.Do()';而是使用类型名称限定它。”

So, I lose access to my inherited method via an instance reference from a static method! 所以,我通过静态方法的实例引用失去了对继承方法的访问权限!

What would be the logic behind it? 它背后的逻辑是什么? Or did I make a typo somewhere? 或者我在某个地方打错了?

I came across this when I was trying to define a static method 'Show' for my form derived from 'Form'. 当我试图为从'Form'派生的表单定义一个静态方法'Show'时,我遇到了这个问题。

Where do you think the bug is? 你认为这个bug在哪里? The fact that there is a warning is absolutely right. 有警告的事实是绝对正确的。 From the C# 3.0 spec, section 10.3.4: 从C#3.0规范,第10.3.4节:

A class-member-declaration is permitted to declare a member with the same name or signature as an inherited member. 允许类成员声明声明与继承成员具有相同名称或签名的成员。 When this occurs, the derived class member is said to hide the base class member. 发生这种情况时,称派生类成员隐藏基类成员。 Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. 隐藏继承的成员不会被视为错误,但它确实会导致编译器发出警告。 To suppress the warning, the declaration of the derived class member can include a new modifier to indicate that the derived member is intended to hide the base member. 为了抑制警告,派生类成员的声明可以包含一个new修饰符,以指示派生成员是否要隐藏基本成员。

The fact that your method invocation fails is subtler, but it's basically because the member lookup algorithm picks the static method, and then this part of section 7.5.5.1 is used: 您的方法调用失败的事实是更微妙的,但它基本上是因为成员查找算法选择静态方法,然后使用7.5.5.1节的这一部分:

Final validation of the chosen best method is performed: 执行所选最佳方法的最终验证:

The method is validated in the context of the method group: If the best method is a static method, the method group must have resulted from a simple-name or a member-access through a type. 该方法在方法组的上下文中进行验证:如果最佳方法是静态方法,则方法组必须由简单名称或成员访问类型生成。 If the best method is an instance method, the method group must have resulted from a simple-name, a member-access through a variable or value, or a base-access. 如果最佳方法是实例方法,则方法组必须由简单名称,通过变量或值的成员访问或基本访问产生。 If neither of these requirements is true, a compile-time error occurs. 如果这些要求都不成立,则会发生编译时错误。

No, that makes perfect sense. 不,这很有道理。 This works as expected: 这按预期工作:

using System;
using System.Collections.Generic;

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { 
    new public static void Do() 
    { ((Foo)new Bar()).Do();/*...*/ } /*...*/ 
}

That's because the compiler assumes that you have a Bar type, and then finds the static member. 那是因为编译器假定您有一个Bar类型,然后找到静态成员。 By casting it to Foo (which comes for free btw.) you make it look in the metdadata for Foo() and all is fine. 通过将它转换为Foo(它是免费的btw。),你可以在foo()的元数据中查看它,一切都很好。

Try this: 尝试这个:

        new public static void Do()
        { 
            ((Foo)new Bar()).Do(); 
        }

你应该能够通过调用base.Do()而不是Bar()调用它.Do()

在最终的代码示例中,Bar.Do()声明中的new关键字意味着您打算隐藏Foo.Do()。

Out of curiosity, why do you want to do this? 出于好奇,你为什么要这样做? It seems like you are probably going about your solution the wrong way. 看起来你可能正在以错误的方式解决你的解决方案。

The above code appears to work as it should, and the compiler messages tell you what the problems are. 上面的代码看起来应该正常工作,编译器消息告诉你问题是什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM