首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >构造函数中的虚拟成员调用

构造函数中的虚拟成员调用
EN

Stack Overflow用户
提问于 2008-09-23 07:11:30
回答 18查看 197.5K关注 0票数 1.4K

我从ReSharper收到一个警告,说我的对象构造函数调用了一个虚拟成员。

为什么这是不能做的事情呢?

EN

回答 18

Stack Overflow用户

回答已采纳

发布于 2008-09-23 07:21:14

当用C#编写的对象被构造时,会发生的情况是,初始化器按照从派生最多的类到基类的顺序运行,然后构造函数按照从基类到派生最多的类(see Eric Lippert's blog for details as to why this is)的顺序运行。

同样在.NET中,对象在构造时不会改变类型,而是从派生最多的类型开始,方法表用于派生最多的类型。这意味着虚方法调用总是在派生最多的类型上运行。

当您将这两个事实结合在一起时,您会遇到这样一个问题:如果在构造函数中进行虚方法调用,并且它不是继承层次结构中派生程度最高的类型,则将在构造函数尚未运行的类上调用它,因此可能不会处于调用该方法的合适状态。

当然,如果您将您的类标记为密封,以确保它是继承层次结构中派生最多的类型,那么这个问题就可以减轻-在这种情况下,调用虚方法是完全安全的。

票数 1.2K
EN

Stack Overflow用户

发布于 2008-09-23 07:17:48

为了回答您的问题,请考虑这个问题:实例化Child对象时,下面的代码将输出什么?

代码语言:javascript
运行
复制
class Parent
{
    public Parent()
    {
        DoSomething();
    }

    protected virtual void DoSomething() 
    {
    }
}

class Child : Parent
{
    private string foo;

    public Child() 
    { 
        foo = "HELLO"; 
    }

    protected override void DoSomething()
    {
        Console.WriteLine(foo.ToLower()); //NullReferenceException!?!
    }
}

答案是,因为foo为空,所以实际上将抛出NullReferenceException。在对象的构造函数之前调用对象的基构造器。通过在对象的构造函数中调用virtual,您引入了这样一种可能性,即继承对象将在它们完全初始化之前执行代码。

票数 727
EN

Stack Overflow用户

发布于 2008-09-23 07:36:09

C#的规则与Java和C++的规则有很大不同。

当您在C#中的某个对象的构造函数中时,该对象以完全初始化(只是不是“构造”)的形式存在,作为它的完全派生类型。

代码语言:javascript
运行
复制
namespace Demo
{
    class A 
    {
      public A()
      {
        System.Console.WriteLine("This is a {0},", this.GetType());
      }
    }

    class B : A
    {      
    }

    // . . .

    B b = new B(); // Output: "This is a Demo.B"
}

这意味着如果从A的构造函数调用虚函数,它将解析为B中的任何覆盖(如果提供了一个覆盖)。

即使你故意像这样设置A和B,完全理解系统的行为,你以后也可能会感到震惊。假设您在B的构造函数中调用了虚函数,“知道”它们将由B或A适当地处理。然后随着时间的推移,其他人决定他们需要定义C,并覆盖那里的一些虚拟函数。突然之间,B的构造函数最终调用了C语言的代码,这可能会导致非常令人惊讶的行为。

不管怎样,在构造函数中避免使用虚函数可能是个好主意,因为C#、C++和Java之间的规则非常不同。您的程序员可能不知道会发生什么!

票数 166
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/119506

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档