第一个被称为链式构造函数的1个理由是什么?

时间:2009-02-05 17:07:02

标签: c#

有人能给我一个很好的理由,为什么在C#中,链式构造函数总是在任何构造函数体之前被调用?

.NET允许您在构造函数中的任何位置调用链式构造函数,那么为什么C#强制您在构造函数体执行之前执行它?

我曾写信给安德斯H并问过他,尽管他一定很忙,但他还是很乐意花时间回复。不幸的是,他设法回答了我实际上没有问过的问题(关于命名的构造函数。)

所以,出于好奇,我想我会在这里问,因为我个人认为这个限制没有一个合理的理由,所以希望我会受到重新教育: - )

只是澄清一下。 .NET CLR规则是必须调用1个构造函数,只有1个构造函数,并且只能调用一次。所以在CLR中这些是有效的

public class Meh
{
  public Meh()
  {
    Console.WriteLine("Meh()");
    this("Hello");
  }

  public Meh(string message)
  {
    Console.WriteLine("Meh {0}", message);
    base();
  }
}

但不是在C#

6 个答案:

答案 0 :(得分:6)

使链式构造函数首先执行保证所有基类元素至少在派生类中可用,因为它们在基类中。允许链接的构造函数在任意点执行将是一种权衡,几乎没有明显的好处。

允许链式构造函数的任意入口点也会阻止延迟创建基类,因为这样的特性可能会运行链式构造函数两次。

答案 1 :(得分:1)

/ *因为您可以在delphi中执行以下注释代码 公共类BaseClass     {         public BaseClass(s​​tring sSql)         {             ExecSQL(sSql);             //执行查询         }     }

public class DerivedClass : BaseClass
{
    public DerivedClass(int i, DateTime dt)
    {
        string sSql = "";
        //construct sSql based on i, dt
        base(sSql);
        //do something else
    }
}      

* /

//按照以下代码处理基本construtor代码。     公共类BaseClass     {         public BaseClass()         {             //没做什么         }

    public BaseClass(string sSql)
    {
        ExecSQL(sSql);
        //DO NOT do anything else
    }    

    public BaseClass(int i, DateTime dt)
    {
        //in base class ignore the parameters.
        string sWhereClause = "";
        string sSql = setSQL(sWhereClause);
        ExecSQL(sWhereClause);
        //DO NOT do anything else
    }

   protected virtual string setSQL(string value)
   {
       //set the sql
       string sSql = "";
       //add value into sSql
       return sSql;
   }

   protected virtual void ExecSQL(string sSql)
   {
       int i = 1;
       //execute query            
   }
}

public class DerivedClass: BaseClass 
{
    //public DerivedClass(string sSql):base (sSql){}
    public DerivedClass()
    {
        //do nothing
    }

    public DerivedClass(string sSql)
    {
        ExecSQL(sSql);
       //DO NOT do anything else
    }

    public DerivedClass(int i, DateTime dt)
    {
        ExecSQL(i, dt);
        //do something else after base execution
    }

   protected void ExecSQL(int i, DateTime dt) //overloaded procedure
   {
       string sWhereClause = "";
       //construct wherclause based on i, dt
       string sSql = setSQL(sWhereClause); //calls baseclass function
       base.ExecSQL(sWhereClause); //calls baseclass procedure
   }       
}

DerivedClass mdD = new DerivedClass(2,DateTime.Now); BaseClass mdB = new BaseClass(“sql”);

答案 2 :(得分:0)

既然你说“主观”,我想你不是在追求历史原因;这样:

  1. 这就是C ++的用法。
  2. 为什么不想构建基类?
  3. 值得使语言更复杂,以容纳你提到的任何罕见用例作为'2'的答案。

答案 3 :(得分:0)

因此它与基本构造函数一致。当您使用:base()引用它们时,在构造函数之前调用基类构造函数,因此它有意义:this()具有相同的语义。

另外,没有一个明智的用例可以让它以相反的方式运作。

答案 4 :(得分:0)

如果有正确的理由不应该提供此功能,那么CLR或其他.NET语言将不支持它。我只能得出结论,答案是其中之一“因为它总是这样”,并且限制可能只是从C ++或其他东西复制。

答案 5 :(得分:0)

当您传递基础构造函数的参数需要验证检查时,这是一个问题。这不应该在基础构造函数中完成,也不能在派生类中完成。

(我在这里假设一个人不会有一个无参数的构造函数。我不能在我的情况下拥有它,因为它要求不应该有一个。)

我无法看到一个优雅的解决方案。