2017-02-15 52 views
3

可有人请敷衍我详细下列情况下,这将是,如果解释为包括三种情况下的内存分配和引用更方便:为什么以下案件的执行流程不同?

  1. 如何流动在三种情况下执行?
  2. 为什么这三种情况下的流程不同?
  3. 尽管两个类之间存在循环依赖关系,但为什么仅在单个案例1失败时才执行案例1?

情况下,一个

namespace CircularDependency_1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      A a = new A(); 
      Console.WriteLine("executed"); 
      Console.ReadLine(); 
     } 
    } 

    public class B 
    { 
     public static A a = new A(); 

     public B() 
     { 

      Console.WriteLine("Creating B"); 
     } 
    } 

    public class A 
    { 
     public static B b = new B(); 

     public A() 
     {   
      Console.WriteLine("Creating A"); 
     } 
    } 
} 

输出

Creating A 
Creating B 
Creating A 
executed 

情况下,两个

namespace CircularDependency_1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      A a = new A(); 
      Console.WriteLine("executed"); 
      Console.ReadLine(); 
     } 
    } 

    public class B 
    { 
     public static A a; 

     public B() 
     { 
      a = new A(); 
      Console.WriteLine("Creating B"); 
     } 
    } 

    public class A 
    { 
     public static B b; 

     public A() 
     {  
      b = new B(); 
      Console.WriteLine("Creating A"); 
     } 
    } 
} 

OUTPUT 由于StackOverflowException,进程终止。

情况下为三个

namespace CircularDependency_1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      A a = new A(); 
      Console.WriteLine("executed"); 
      Console.ReadLine(); 
     } 
    } 

    public class B 
    { 
     public A a; 

     public B() 
     { 
      a = new A(); 
      Console.WriteLine("Creating B"); 
     } 
    } 

    public class A 
    { 
     public B b; 

     public A() 
     {  
      b = new B(); 
      Console.WriteLine("Creating A"); 
     } 
    } 
} 

OUTPUT 过程由于StackOverflowException终止。

+0

你为什么包含'java'标签? – SomeDude

+0

@svasa我认为这个问题更多的是OOPS而不是面向语言 –

+1

我投票结束这个问题作为题外话,因为[问题要求作业帮助必须包括你迄今为止所做的工作的总结问题以及你解决问题的难点描述](http://stackoverflow.com/help/on-topic)。 – RealSkeptic

回答

2

@多才多艺,你很接近,但不正确。第一种情况执行和其他两种情况失败的原因不仅仅是因为对象是在构造函数内部还是在类内部(构造函数之外)创建的。为了证明这一点,请尝试分别在BA类(第一种情况)中使ab字段不是静态的;你会发现它会失败,即使这些对象是在构造函数之外创建的。

由于@Versatile解释的原因,案例2和3失败。 由于static成员,因此执行了第1种情况。 让我们来看看流程:

Main方法中,行A a = new A()开始创建a对象。在此过程中,将创建类B的对象,因为行public static B b = new B() - 由于B类的主体中的行public static A a = new A(),该行将开始创建类A的另一个对象。现在,这里出现了魔法(不会触发循环依赖)。这条线,public static A a = new A()将开始创建A类的另一个对象,在创建此对象时,它不会创建B类的另一个对象,因为它是A的静态成员,并且它已创建。我们知道,类的静态成员在类的所有实例之间共享。因此,它不会触发创建类B的另一个对象。总的来说,我们最终得到三个类的实例:AB,A

UPDATE

有趣的观察,在第一种情况下,如果我们初始化构造函数中的静态成员会发生什么。尽管AB类声明了静态成员,但由于循环依赖性,执行将失败。这是因为静态成员在执行构造函数之前未被初始化。

+0

感谢您指出。我认为静态的使用很明显,对象只会创建一次,而且因为它在该行被分配了新的内存,因此它不会进入递归调用。 – Versatile

1

1.这三种情况下的流程是如何执行的? 首先调用static void Main(),然后调用对象A的构造函数,因为代码行A a = new A();

2.为什么这三种情况下的流程不同?

3.虽然两个类之间存在循环依赖关系,但为什么仅在第一种情况下才执行第一种情况,而其余的情况都是失败的?

由于相同的原因,观察到上述两种情况。如果仔细观察,则按如下方式分配内存。 Case1中的类而不是构造函数。即

public class A 
{ 
    public static B b = new B(); 
} 

此外的对象是静态的,所以它将被创建只有一次,因为这是创建一次,其在同一行分配存储器获取仅执行一次。

情况2和情况3:存储器到对象A和B在构造器中分配,即在A的构造器中,存储器被分配给B,而在B的构造器中,存储器被分配给A,这导致调用相应的类一次又一次地构造函数,直到抛出一个异常。

相关问题