C# 什么是阴影?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/673779/
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
What is Shadowing?
提问by
回答by Kent Boogaart
- Overriding : redefining an existing method on a base class
- Shadowing : creating an entirely new method with the same signature as one in a base class
- 覆盖:重新定义基类上的现有方法
- 阴影:创建一个全新的方法,其签名与基类中的方法相同
回答by Noldorin
Here's an MSDN articleon Shadowing. The language examples are in Visual Basic (unfortunately there is no equivalent C# page on MSDN), but it deals generally with the concepts and hopefully should help you understand anyway.
这是关于阴影的MSDN 文章。语言示例在 Visual Basic 中(不幸的是,MSDN 上没有等效的 C# 页面),但它通常涉及概念,希望无论如何都能帮助您理解。
Edit:Seems like there isa C# articleon shadowing, except that it's called hidingin C#. Also, this pageoffers a good overview.
回答by mqp
Suppose I have a base class that implements a virtual method:
假设我有一个实现虚方法的基类:
public class A
{
public virtual void M() { Console.WriteLine("In A.M()."); }
}
I also have a derived class that also defines a method M:
我还有一个派生类,它也定义了一个方法 M:
public class B : A
{
// could be either "new" or "override", "new" is default
public void M() { Console.WriteLine("In B.M()."); }
}
Now, suppose I write a program like this:
现在,假设我写了一个这样的程序:
A alpha = new B(); // it's really a B but I cast it to an A
alpha.M();
I have two different choices for how I want that to be implemented. The default behavior is to call A's version of M. (This is identical to the behavior if you applied the "new
" keyword to B.M()
.)
对于我希望如何实施,我有两种不同的选择。默认行为是调用 A 的 M 版本。(这与将 " new
" 关键字应用于 的行为相同B.M()
。)
This is called "shadowing" when we have a method with the same name but a different behavior when called from the base class.
当我们有一个名称相同但从基类调用时行为不同的方法时,这称为“阴影”。
Alternately, we could have specified "override
" on B.M()
. In this case, alpha.M()
would have called B's version of M.
或者,我们可以在 上指定“ override
” B.M()
。在这种情况下,alpha.M()
会调用 B 的 M 版本。
回答by Jim Mischel
Shadowing hides a method in a base class. Using the example in the question you linked:
阴影隐藏基类中的方法。使用您链接的问题中的示例:
class A
{
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A
{
public new int Foo() { return 1;}
public override int Bar() {return 1;}
}
Class B
overridesthe virtual method Bar
. It hides(shadows) the non-virtual method Foo
. Override uses the overridekeyword. Shadowing is done with the newkeyword.
类B
覆盖虚方法Bar
。它隐藏(阴影)非虚拟方法Foo
。Override 使用override关键字。阴影是用new关键字完成的。
In the code above, if you didn't use the newkeyword when defining the Foo
method in class B
, you would get this compiler warning:
在上面的代码中,如果在 class 中定义方法时没有使用new关键字,则会收到以下编译器警告:Foo
B
'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
回答by Jeremy
Shadowing isn't something I'd be worried about understanding or implementing unless it "fits" the problem really well. I've seen it used improperly and cause weird logic bugs much more often than being used correctly. The big cause, I think, is when the programmer forgets to put overrides in a method signature then the compiler warning will suggest the new keyword. I've always felt that it should recommend using override instead.
阴影不是我会担心理解或实施的东西,除非它非常“适合”问题。我见过它使用不当,导致奇怪的逻辑错误比正确使用更频繁。我认为,最大的原因是当程序员忘记在方法签名中放置覆盖时,编译器警告会建议使用 new 关键字。我一直觉得它应该推荐使用覆盖来代替。
回答by Jorge Córdoba
Shadowing consist on hiding a base class method with a new definition in a child class.
隐藏包括在子类中隐藏具有新定义的基类方法。
The difference between hiding and overriding has to do with the way methods are invoked.
隐藏和覆盖之间的区别与调用方法的方式有关。
That way, when a virtual method is overridden, the call address for the method call table of the base class is replaced with the address of the child routine.
这样,当一个虚拟方法被覆盖时,基类的方法调用表的调用地址被替换为子例程的地址。
On the other hand, when a method is hidden, a new address is added to the method call table of the child class.
另一方面,当一个方法被隐藏时,会在子类的方法调用表中添加一个新地址。
When a call is made to the method in question:
当调用相关方法时:
- The method call table class type is obtained, if we are invoking with a reference to the base class then the base class method table is obtained, if we have a reference to the child class, then the child class method table is obtained.
- The method is searched in the table, if it's found then the invocation takes place, otherwise the base class method table is searched.
- 获取方法调用表类类型,如果是引用基类调用则获取基类方法表,如果引用子类则获取子类方法表。
- 在表中搜索该方法,如果找到则调用发生,否则搜索基类方法表。
If we invoke the method with a reference to the child class then the behavior is the same, if the method has been overridden, the method address will be found in the base class, if the method was hidden the method address will be found on the child class, and since it has been already found, base class table will not be searched.
如果我们引用子类来调用方法,那么行为是一样的,如果方法被覆盖,方法地址将在基类中找到,如果方法被隐藏,方法地址将在基类中找到子类,因为已经找到了,所以不会搜索基类表。
If we invoke the method with a reference to the base class then behavior changes. When overriding, as the method address overwrites base class entry, we will call the child method, even when holding a reference to the base class. With shadowing, the base class method table (which is the only one visible as we hold a reference to the base class) contains the virtual method address, and therefore, the base class method will be called.
如果我们使用对基类的引用来调用该方法,则行为会发生变化。覆盖时,由于方法地址覆盖了基类入口,我们将调用子方法,即使持有对基类的引用。使用阴影,基类方法表(这是唯一可见的,因为我们持有对基类的引用)包含虚拟方法地址,因此,基类方法将被调用。
In general shadowing is a bad idea, as it introduces a difference on the behavior of an instance depending on the reference we have to it.
一般来说,阴影是一个坏主意,因为它根据我们对它的引用引入了实例行为的差异。
回答by JaredPar
Expanding on Kent's correct answer
扩展肯特的正确答案
When disambiguating when which method will be called, I like to think of shadowing vs. overriding with the following
在消除何时调用哪个方法的歧义时,我喜欢考虑使用以下内容进行遮蔽与覆盖
- Shadowing: The method called depends on the type of the reference at the point the call is made
- Overriding: The method called depends on the type of the object at the point the call is made.
- 阴影:调用的方法取决于调用时引用的类型
- 覆盖:调用的方法取决于调用时对象的类型。
回答by dhaval8087
private static int x = 10;
static void Main(string[] args)
{ int x = 20;
if (Program.x == 10)
{
Console.WriteLine(Program.x);
}
Console.WriteLine(x);}
Output:
输出:
10 20
10 20
回答by Mathew M
If you want to hide Base class method , Use override in base [virtual method in base]
如果要隐藏基类方法,请在基中使用覆盖[基中的虚拟方法]
if you want to hide Child class method , Use new in base [nonvirtual method in base]->shadow
如果要隐藏子类方法,请在基中使用 new [基中的非虚拟方法]->shadow
Base B=new Child()
B.VirtualMethod()
-> Calls Child class method
B.VirtualMethod()
-> 调用子类方法
B.NonVirtualMethod()
-> Calls Base class method
B.NonVirtualMethod()
-> 调用基类方法
回答by Kamran Bigdely
Overriding: same name and exactly the same parameters, implemented differently in sub classes.
覆盖:相同的名称和完全相同的参数,在子类中实现不同。
- If treated as DerivedClass or BaseClass, it used derived method.
- 如果被视为 DerivedClass 或 BaseClass,则使用派生方法。
Shadowing: same name and exactly the same parameters, implemented differently in sub classes.
阴影:相同的名称和完全相同的参数,在子类中实现不同。
- If treated as DerivedClass, it used derived method.
- if treated as BaseClass, it uses base method.
- 如果视为 DerivedClass,则使用派生方法。
- 如果被视为 BaseClass,则使用 base 方法。