Visual Studio C#虚拟重写关键字(& O)

ukxgm1gy  于 2023-03-24  发布在  C#
关注(0)|答案(7)|浏览(228)

我以为我已经确定了这一点,然后我去看看一些源在工作中,我想知道为什么有这么多的矛盾,我从msdn读到的和我看到的源…。
我的理解是,virtual关键字可以在方法声明中使用,以允许任何派生类覆盖它。
在实现超类的虚方法时,需要在派生类中使用override关键字......
例如:

public abstract class A
{
    public virtual string GetName();
}

public class B:A
{

    //assume there are some defined properties.
    public override string GetName()
    {
        return FirstName;
    }
}

我有几个问题:
1)如果一个方法没有实现,那么真的有必要将它定义为virtual吗?当然,它可以在子类中被覆盖,而不需要使用virtual和override?
2)如果(1)是不正确的,那么我认为每个虚方法都必须在使用它的子类中被重写的想法是正确的吗?
编辑:
你是对的,我的代码无法编译...我想知道为什么....我理解你的答案,但后来我看到了这个:

public abstract class RequestHandler<TRequest, TResponse> : RequestHandler, IRequestHandler<TRequest>, IRequestHandler, IDisposable, ITypedRequestHandler
    where TRequest : global::Agatha.Common.Request
    where TResponse : global::Agatha.Common.Response, new()
{
    protected RequestHandler();

    public virtual void AfterHandle(TRequest request);
    public virtual void BeforeHandle(TRequest request);
    public override Response CreateDefaultResponse();
    public TResponse CreateTypedResponse();
    public override Response Handle(Request request);
    public abstract Response Handle(TRequest request);
}

以上内容不会导致编译器抱怨...

nxowjjhe

nxowjjhe1#

首先,上面的代码是无效的。虚方法仍然必须有一个默认实现的主体。要做到上面所做的,你需要使用abstract关键字而不是virtual。
abstract意味着没有提供方法体,但是从它派生的任何类都必须实现这个方法(除非它也是抽象的)。
我想这基本上回答了你的问题……
1.如果它没有实现,那么它 * 不能 * 是虚拟的,它必须是抽象的。如果它有一个什么都不做的实现,那么它必须被实现。
1.虚类的全部意义在于它有默认的行为,所以你可以选择是否覆盖它。如果它是抽象的,那么你必须覆盖它(除非你派生另一个抽象类)。

v8wbuo2f

v8wbuo2f2#

如果一个方法没有实现,真的有必要将它定义为虚方法吗?
你可以使方法抽象(这将隐式地使它虚拟)。
当然,它可以在子类中被覆盖,而不需要使用virtual和override?
如果你只是“覆盖”它,而没有显式地覆盖它,它不会是同一个方法,并且在基类的变量上调用该方法不会调用派生方法(它不会参与多态)。您将只是“隐藏”基类的方法(编译器实际上会警告你这一点,如果你真的想这么做,你必须使用new修饰符。
举个例子会更清楚:

class B
{
    public virtual void M() { Console.WriteLine("B.M") };
}

class D1 : Base
{
    // Hides the base method
    public new void M() { Console.WriteLine("D1.M") };
}

class D2 : Base
{
    // Overrides the base method
    public override void M() { Console.WriteLine("D2.M") };
}

...

D1 d1 = new D1();
d1.M(); // Prints "D1.M"
B b1 = d1;
b1.M(); // Prints "B.M", because D1.M doesn't override B.M

D2 d2 = new D1();
d2.M(); // Prints "D2.M"
B b2 = d2;
b2.M(); // Also prints "D2.M", because D2.M overrides B.M

如果(1)是不正确的,那么我认为每个虚方法都必须在使用它的子类中被重写的想法是正确的吗?
不,只有当它是抽象的……虚方法可以有一个实现,在这种情况下,派生类不会被迫重写它。

js4nwp54

js4nwp543#

1)如果一个方法没有实现,那么真的有必要将它定义为virtual吗?当然,它可以在子类中被覆盖,而不需要使用virtual和override?
正如其他答案中所说,virtual方法需要有实现。你把它和abstract弄混了。
如果你问virtual方法是否需要声明为virtual:在C#中,是的,这是必要的。在Java中,你可以覆盖任何旧的方法。这是C#的设计决定,要求使用virtual关键字进行覆盖,这样除非程序员有意,否则方法不能被覆盖。
如果程序员没有通过不使用virtual来表达意图,您仍然可以使用new关键字“覆盖”方法。然而,这有点不同。希望这段代码有助于说明概念:

class Program
{
    static void Main(string[] args)
    {
        var baseC = new BaseClass();
        var extC = new ExtClass();
        var lazyC = new LazyClass();

        Console.WriteLine(baseC.NewMethod());
        Console.WriteLine(baseC.VirtualOverrideMethod());

        Console.WriteLine("---");

        Console.WriteLine(extC.NewMethod());
        Console.WriteLine(extC.VirtualOverrideMethod());

        Console.WriteLine("---");

        Console.WriteLine(((BaseClass) extC).NewMethod());
        Console.WriteLine(((BaseClass) extC).VirtualOverrideMethod()); // Redundant typecast

        Console.WriteLine("---");

        Console.WriteLine(lazyC.VirtualOverrideMethod());

        Console.ReadKey();
    }

    public class BaseClass
    {
        public BaseClass()
        {

        }

        public string NewMethod()
        {
            return "NewMethod of BaseClass";
        }

        public virtual string VirtualOverrideMethod()
        {
            return "VirtualOverrideMethod of BaseClass";
        }
    }

    class ExtClass : BaseClass
    {
        public new string NewMethod()
        {
            return "NewMethod of ExtClass";
        }

        public override string VirtualOverrideMethod()
        {
            return "VirtualOverrideMethod of ExtClass";
        }
    }

    class LazyClass : BaseClass
    {
    }
}

输出:

NewMethod of BaseClass
VirtualOverrideMethod of BaseClass
---
NewMethod of ExtClass
VirtualOverrideMethod of ExtClass
---
NewMethod of BaseClass
VirtualOverrideMethod of ExtClass
---
VirtualOverrideMethod of BaseClass

2)如果(1)是不正确的,那么我认为每个虚方法都必须在使用它的子类中被重写的想法是正确的吗?
一点也不。virtual是一种说法,“如果你想覆盖这个方法,没关系”。事实上,我在上面的代码中包含了LazyClass来显示这一点。
以上内容不会导致编译器抱怨...
我不太使用接口,但这看起来像一个。在我的代码中,如果我更改

class ExtClass : BaseClass
    {
        public new string NewMethod()
        {
            return "NewMethod of ExtClass";
        }

        public override string VirtualOverrideMethod()
        {
            return "VirtualOverrideMethod of ExtClass";
        }
    }

致:

class ExtClass : BaseClass
    {
        public new string NewMethod()
        {
            return "NewMethod of ExtClass";
        }

        public override string VirtualOverrideMethod()
        {
            return "VirtualOverrideMethod of ExtClass";
        }
    }

我得到:

error CS0501: 'OverrideTest.Program.ExtClass.VirtualOverrideMethod()' must declare a body because it is not marked abstract, extern, or partial

来自Visual Studio 2010。我的BaseClassvirtual方法也是如此。

rggaifut

rggaifut4#

virtual的需求是由多态性决定的。想想当你使用new在子类中重新定义一个方法时会发生什么:

class Parent
{
    void Foo() { Console.WriteLine("Parent"); }
    virtual void Bar { Console.WriteLine("Parent"); }
}

class Child : Parent
{
    new void Foo() { Console.WriteLine("Child"); } // another method Foo
    override void Bar { Console.WriteLine("Child"); }
}

var child = new Child();    // a Child instance
var parent = (Parent)child; // same object, but statically typed as Parent

c.Bar(); // prints "Child"
p.Bar(); // again, prints "Child" -- expected virtual behavior

c.Foo(); // prints "Child"
p.Foo(); // but this prints "Parent"!!

由于这个原因,要从sealed派生的类(即不是sealed)应该总是将可以被重写的方法标记为virtual-否则会出现上面这样令人困惑的运行时行为。关键在于它的行为方式不同。

6l7fqoea

6l7fqoea5#

好的,通过将方法声明为virtual(并且不希望覆盖子类中的方法),如果你要将同名的方法引入子类中,你将进入方法隐藏的世界。你必须这样定义它:

public abstract class A
{
    public virtual string GetName()
    {
        return null;
    }
}

public class B : A
{
    //assume there are some defined properties.
    public new string GetName()
    {
        return FirstName;
    }
}

我建议您考虑抽象覆盖方法:

public abstract class A
{
    public abstract string GetName()
}

// to override
public class B : A
{
    //assume there are some defined properties.
    public override string GetName()
    {
        return FirstName;
    }
}

这将是非常不同的。2我强烈建议你只覆盖子类中的抽象方法。
然而,这里有一个关于这个问题的快速参考(旧的,但很好的阅读):
http://www.akadia.com/services/dotnet_polymorphism.html

vnzz0bqm

vnzz0bqm6#

1)如果一个方法没有实现,那么真的有必要将它定义为virtual吗?当然,它可以在子类中被覆盖,而不需要使用virtual和override?
你可以使用一个abstract方法,它没有主体,但是如果你从那个类派生,你必须重写那个方法。所有的abstact方法都必须在子类中被重写。
2)如果(1)是不正确的,那么我认为每个虚方法都必须在使用它的子类中被重写的想法是正确的吗?
不,相反,你可以使用一个virtual关键字在里面有一个实现,但是不要在子类中强制重写。从这个Angular 来看,给你更多的灵活性。
通常他们使用abstract来为查尔兹创建严格的约束,所以从它派生的每个子对象必须实现基类的指定成员。

igetnqfo

igetnqfo7#

这就是virtualabstract方法的区别:

方法可以被派生类覆盖,如果派生类选择覆盖,虚方法可能有也可能没有默认实现供继承者调用,这是通过base关键字完成的。
抽象方法必须被派生类覆盖,其约束条件为:

  • 它只能在抽象类中定义。
  • 它不能有实现,因为它是由继承者来定义其行为的。

相关问题