Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中阴影和覆盖的区别?_C# - Fatal编程技术网

C#中阴影和覆盖的区别?

C#中阴影和覆盖的区别?,c#,C#,隐藏和重写C#中的一个方法有什么区别?我认为主要的区别在于,使用隐藏时,基本上是重用名称,而忽略了超类的使用。通过重写,您可以更改实现,但不能更改可访问性和签名(例如参数类型和返回)。请参阅。井继承 假设您有以下类: class A { public int Foo(){ return 5;} public virtual int Bar(){return 5;} } class B : A{ public new int Foo() { return 1;} //sh

隐藏重写C#中的一个方法有什么区别?

我认为主要的区别在于,使用隐藏时,基本上是重用名称,而忽略了超类的使用。通过重写,您可以更改实现,但不能更改可访问性和签名(例如参数类型和返回)。请参阅。

井继承

假设您有以下类:

class A {
   public int Foo(){ return 5;}
   public virtual int Bar(){return 5;}
}
class B : A{
   public new int Foo() { return 1;}     //shadow
   public override int Bar() {return 1;} //override
}
那么当你称之为:

A clA = new A();
B clB = new B();

Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1

//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1
A clA=newa();
B clB=新的B();
Console.WriteLine(clA.Foo());//产出5
Console.WriteLine(clA.Bar());//产出5
Console.WriteLine(clB.Foo());//产出1
Console.WriteLine(clB.Bar());//产出1
//现在让我们把B投给A班

Console.WriteLine(((A)clB.Foo());//输出5阴影实际上是VB术语,我们称之为隐藏在C#中

通常,隐藏(VB中的阴影)和覆盖如答案所示

虚拟方法显示为被子类重写,即使在超类类型上或从超类的内部代码调用该方法,也会从子类调用替换实现

然后,在定义子类上具有相同签名的方法时,通过使用
new
关键字隐藏具体方法(未标记为虚拟或抽象的方法)。在这种情况下,当在使用原始实现的超类类型上调用该方法时,新实现仅在子类上可用

然而,经常被忽略的是,还可以隐藏虚拟方法

class A
{
    public virtual void DoStuff() { // original implementation }
}

class B : A
{
    public new void DoStuff() {  //new implementation }
}

B b = new B();
A a = b;

b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.
注:在上述示例中,DoStuff变为混凝土,无法覆盖。但是,也可以同时使用
virtual
new
关键字

class A
{
    public virtual void DoStuff() { // original implementation }
}

class B : A
{
    public new virtual void DoStuff() {  //new implementation }
}

class C : B
{
    public override void DoStuff() { //replacement implementation }
}

C c = new C();
B b = c;
A a = b;

c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.
请注意,尽管涉及的所有方法都是虚拟的,但C上的重写不会影响A上的虚拟方法,因为B中使用的
new
隐藏了A实现

编辑:在对该答案的评论中指出,上述内容可能很危险,或者至少不是特别有用。我会说,是的,这可能是危险的,如果有用的话,它也会存在

特别是,如果同时更改可访问性修饰符,可能会遇到各种各样的麻烦。例如:-

public class Foo
{
    internal Foo() { }
    protected virtual string Thing() { return "foo"; }
}

public class Bar : Foo
{
 internal new string Thing() { return "bar"; }
}
对于
Bar
的外部继承者,
Foo
的Thing()实现仍然是可访问和可重写的。根据.NET类型规则,所有合法且可解释的内容都不会完全不符合实际


我发布这个答案是为了加深对事物如何工作的理解,而不是作为一个可以自由使用的技术建议。

基本上,如果你有如下内容

Class A
{
}

Class B:A
{
}

A a = new B();
您对对象“a”调用的任何方法都将对“a”类型(此处类型为“a”)进行生成 但是,如果您在类B中实现了类A中已经存在的相同方法,编译器将警告您使用“New”关键字。如果使用“新建”,警告将消失。除此之外,在继承的类中使用“New”与不使用它没有区别

在某些情况下,您可能需要调用特定实例当时持有的引用类的方法,而不是调用对象类型的方法。在上述情况下,它持有的引用是“B”,但类型是“A”。因此,如果您希望方法调用应该发生在“B”上,那么您可以使用Virtual和override来实现这一点

希望这有助于


Daniel Sandeep.

阴影是一个VB.NET概念。在C#中,阴影被称为隐藏。它隐藏了派生类方法。它是使用“new”关键字完成的


Override关键字用于在派生类中提供基类方法(标记为“Virtual”)的全新实现。

如果出现无法更改类内容的情况,比如说
a
,但您希望使用它的一些方法以及一个通用名称的方法,您可以通过
new
关键字使用自己的方法实现

关键是使用它,引用和对象必须是同一类型

class A
{
    public void Test()
    {
        Console.WriteLine("base");
    }
}

class B : A
{
    public new void Test()
    {
        Console.WriteLine("sub");
    }

    public static void Main(string[] args)
    {
        A a = new A();
        B aa = new B();
        a.Test();
        aa.Test();
    }
}

覆盖提供多态性,阴影在该层次结构级别提供不同的实现,但不是多态性。@dribeas,您将使用什么多态性定义来得出这一结论?@AnthonyWJones,多态性是一个(派生)类型用作不同(基)的能力类型,其中实际实现(行为)是实际特定(派生)类型的实现(行为)。若重写,派生方法将通过对base的引用来调用,但若在我看来不是true,那个么示例代码中就有一个错误。强制转换应该是((A)clB.Foo(),不是吗?不,因为bar是虚拟的,所以它仍然会调用B BarNice来知道这一点。虽然它的使用可能是危险的:)所有工具如果使用不当都可能是危险的。但是,它的可用性似乎真的有问题!是否有任何“严肃”的开源应用程序使用此?可用性?你是说有用吗?有些边缘的东西在你需要之前可能看起来毫无用处。似乎只有在虚拟和新的游戏中才会出现阴影@Stormenet只是解释了重写的事情,因为类调用自己的方法是正常的行为,除非它是虚拟的。它隐藏派生类方法,而使用基类方法?