2011-08-03 20 views
0

考虑下面的代码为什么对象是孤儿,当创作者存在

public class City 
    { 
     public string Name { get { return "New York"; } } 

     Building empEstate; 
     Building nyTimes; 
     public void Init() 
     { 
      // I hate passing "this" to all object 
      empEstate = new EmpEstate(this); 
      setSomeProperty(empEstate); 
      // any one can create new object of some other city 
      // and pass to the building 
      nyTimes = new NYTimes(this); 
      ... 
      other = new OtherBuildings(this) 
     } 

     public void PrintAddresses() 
     { 
      empEstate.Print(); 
      nyTimes.Print(); 
      ... 
      other.Print(); 
     } 
    } 

    public abstract class Building { 
     City _city; 
     public Building(City city){ 
      this._city = city; 
     } 
     public abstract string Name { get;} 
     public void Print(){ 
      Console.WriteLine(this.Name); 
      Console.Write(","); 
      Console.WriteLine(this._city.Name); 
     } 
    } 
  1. 我想更好的解决方案,以这种方法的第一件事。打印只是一个例子。其实每个建筑物都会向City物件提出一些事件。我不想为每座建筑物添加处理程序,因为城市中可能有几座建筑物。此外,我不想将它们中的每一个都添加到列表中,因为它是每个建筑的两个任务(一个初始化和第二个添加到列表中,一个在编写新建筑时忘记添加到列表中)。为此,我希望调用者自动可用于被调用者,如控件的父属性(尽管它已添加到this.Controls中)

  2. 使用内存,我们可以知道当前对象的父代是谁。 GC如何知道该对象未被引用(包括创建者)。我们不能使用内存创建一个方法(安全或不安全)来识别调用者对象。我看到我们可以使用StackTrace来查看调用hirarchy,我们可以在创建新对象时在这里拦截。

+0

你甚至认为'父'是什么? – CodesInChaos

+0

父母可以说对象被声明或创建的对象。 – hungryMind

回答

1

建厂解决我的这个传递到每个对象

public interface ICity 
    { 
     string Name { get; } 
    } 
    public abstract class City : ICity 
    { 
     public T CreateBuilding<T>() 
     { 
      T buildingInstance = Activator.CreateInstance<T>(); 
      ((IBuilding)buildingInstance).SetCity(this); 
      return buildingInstance; 
     } 

     public abstract string Name { get; } 
    } 

    interface IBuilding 
    { 
     ICity City { get; } 
     void SetCity(ICity city); 
    } 
    public abstract class Building : IBuilding 
    { 
     private ICity _city; 
     public ICity City { get { return _city; } } 
     public void IBuilding.SetCity(ICity city) 
     { 
      this._city = city; 
     } 
     public abstract string Name { get; } 
     public void Print() 
     { 
      Console.WriteLine(this.Name); 
      Console.Write(","); 
      Console.WriteLine(this._city.Name); 
     } 
    } 
    public class EmpEstate : Building 
    { 
     public override string Name { get { return "Emp State"; } } 
    } 
    public class NYTimes : Building 
    { 
     public override string Name { get { return "NY Times"; } } 
    } 
    public class NewYorkCity : City 
    { 
     public override string Name { get { return "New York"; } } 

     EmpEstate empEstate; 
     NYTimes nyTimes; 
     public void Init() 
     { 
      // Now I dont need to pass this 
      empEstate = this.CreateBuilding<EmpEstate>(); 
      setSomeProperty(empEstate); 
      // now any one cannot create building in new your and 
      // say it belongs to Philedelphia :) 
      nyTimes = this.CreateBuilding<NYTimes>(); 
     } 

     public void PrintAddresses() 
     { 
      empEstate.Print(); 
      nyTimes.Print(); 
     } 
    } 

问题的问题在那里已经创建了几个类和新的功能,我们需要在基类建筑物对象的创建者对象。我们不想修改每个类的构造函数,并将这个对象传递给每个类。 City类(例如)基本上是插件端的代码,所以允许它们通过城市(如果插件开发者通过错误的城市)可能会扰乱整个应用程序的功能。所以修改插件基础解决了我的目的。欢迎提出建议。

0

对象没有逻辑“拥有者”。检查堆栈跟踪...通常不是理想的。与Parent相比,这与现有方法并无太大差别 - 只是通过方法/属性而不是构造函数来设置。

如果城市仅适用于像Print方法的背景下有必要,为什么不把它作为一个参数,即nyTimes.Print(this)等,如果你可能需要其他的值,而不是拍了很多的参数,可以考虑使用一些那种情境对象一个城市 - 即

class PrintContext { 
    public City City {get;private set;} 
    // other stuff... 
    public PrintContext(City city/*, other stuff...*/) { 
      City = city; 
    } 
} 
+0

我喜欢你的想法作为PrintContext,但就像我说的城市需要处理每个建筑引发的事件,这里这种方法将无法正常工作。 – hungryMind

0

我认为你是滥用条款创造者。创建实例的对象与实例没有特殊关系(例如,工厂创建对象,但不保留对它们的引用),因此,通常无法找出创建具体实例的人或创建的内容。
在同样的意义上,亲本在一般对象上没有意义。我们可以以某种方式推断Form是TextBox的父类,但这不是特别的关系。在这种情况下,它仅表示TextBox在窗体的Contols集合中,并且它的Parent被设置为Form。

这是正确的,这可能会导致不一致(Form1认为TextBox是它的孩子,但TextBox认为它是Parent是Form2),但我不知道,也不认为有更好的这种关系的解决方案比Children集合/ Parent的参考。

0

挑选一些您的许多问题:

我不喜欢通过这个

为什么?你正在告诉建筑物属于哪个城市。你还能怎么做呢?我将这看作是将物体连接在一起的常见习惯用语。

此外,我不希望他们每个人添加到列表中,因为它是每个二期建设任务 (一个初始化和第二添加到列表中,一个 忘记添加书写新的建筑时列出)。

我不清楚你想将它们添加到列表什么,而是你对关注,如果你做的工作在基础构造“遗忘”被克服:

public Building(City city){ 
     this._city = city; 
     // add the building to the list here - nothing to "forget" 
    } 

至于GC,一旦创造者创造了一些东西,除非你选择保留一个参考,否则它们之间没有任何关系。你这样做,是与

empEstate = new EmpEstate(this); 

因此只要该城市是不是垃圾收藏品的候选者,则EmpState不会任。在城市