从另一个调用一个构造函数

Avi*_*Avi 927 c# constructor

我有两个构造函数,它们将值提供给只读字段.

public class Sample
{
    public Sample(string theIntAsString)
    {
        int i = int.Parse(theIntAsString);
        _intField = i;
    }

    public Sample(int theInt) => _intField = theInt;
    public int IntProperty    => _intField;

    private readonly int _intField;
}
Run Code Online (Sandbox Code Playgroud)

一个构造函数直接接收值,另一个构造函数进行一些计算并获取值,然后设置字段.

现在这里是抓住:

  1. 我不想复制设置代码.在这种情况下,只设置一个字段,但当然可能不止一个.
  2. 要使字段只读,我需要从构造函数中设置它们,因此我无法将共享代码"提取"到实用程序函数中.
  3. 我不知道如何从另一个构建函数调用.

有任何想法吗?

SLa*_*aks 1536

像这样:

public Sample(string str) : this(int.Parse(str)) { }
Run Code Online (Sandbox Code Playgroud)

  • @Avi:您可以创建一个操作参数的`static`方法. (55认同)
  • @RosdiKasim:基类构造函数总是先运行.在初始化基类之前,不能使用或查看`this`. (19认同)
  • 我可以知道这个的执行顺序吗?`Sample(string)`中的所有内容都将首先执行,然后执行`Sample(int)`或者首先执行int版本然后它将返回到字符串版本?(就像在Java中调用`super()`一样?) (18认同)
  • @ivan_pozdeev:是的,你可以; 使用`?:`或调用静态方法. (4认同)
  • @GeorgeBirbilis:是的.他想在调用另一个ctor之前运行代码(在参数上).那时,没有实例. (3认同)
  • @GeorgeBirbilis:验证或转换参数。 (2认同)
  • @GeorgeBirbilis:实际上,.Net正在逐渐远离这种模式,因为它不适用于不可变类型. (2认同)
  • @RavitD:构造函数调用始终是第一个。 (2认同)

sup*_*cat 154

如果没有在自己的方法中进行初始化(例如因为你想在初始化代码之前做太多,或者将它包装在try-finally中,或者其他什么),那么你想要的东西不能令人满意地实现你可以拥有任何或所有构造函数通过引用初始化例程传递readonly变量,然后初始化例程将能够随意操作它们.

public class Sample
{
    private readonly int _intField;
    public int IntProperty => _intField; 

    private void setupStuff(ref int intField, int newValue) => intField = newValue;

    public Sample(string theIntAsString)
    {
        int i = int.Parse(theIntAsString);
        setupStuff(ref _intField,i);
    }

    public Sample(int theInt) => setupStuff(ref _intField, theInt);
}
Run Code Online (Sandbox Code Playgroud)

  • +1实际解决方案.使用`base(...)`或`this(...)`我们只能执行非常有限的操作. (17认同)
  • @nawfal:因为如果变量是`readonly`就不能这样做. (7认同)
  • 如何使用`out`关键字而不是`ref`? (3认同)
  • 绝对同意 - 另一种解决方案有效,但这不是正确的方法(TM)! (2认同)
  • @JohnCarpenter:如果只需要设置一个`readonly`字段,设置它的代码可以调用方法并使用返回值分配字段,但是任何数量的字段都可以用`ref`直接写入.此外,如果重要,通过`ref`参数进行的更改会立即发生,甚至在函数返回之前,而使用函数返回值进行的更改则不会. (2认同)
  • @JohnB:唯一可以通过`ref`直接传递`readonly`字段的东西是构造函数.函数可以通过`ref`接收任何东西的唯一方法是从一些有权访问它的函数中调用它并且可以传递它.如果构造函数通过`ref`将`readonly`字段传递给它之外的函数,那么该函数可以用与`ref`接收的任何其他函数相同的方式写入字段. (2认同)

Sud*_*ha 58

在构造函数的主体之前,使用以下任一方法:

: base (parameters)

: this (parameters)
Run Code Online (Sandbox Code Playgroud)

例:

public class People: User
{
   public People (int EmpID) : base (EmpID)
   {
      // Add more statements here.
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,如果我需要对构造函数调用之间的参数进行一些操作,则不起作用 (13认同)
  • @Denis在调用构造函数之前你不能做任何事情.如果要在初始化对象的属性之前执行某些操作,请在构造函数示例`init()`以外的方法中移动初始化.您可以从任何构造函数中调用此方法. (2认同)

Fai*_* Mq 9

我正在改进supercat的答案.我想以下也可以做到:

class Sample
{
    private readonly int _intField;
    public int IntProperty
    {
        get { return _intField; }
    }

    void setupStuff(ref int intField, int newValue)
    {
        //Do some stuff here based upon the necessary initialized variables.
        intField = newValue;
    }

    public Sample(string theIntAsString, bool? doStuff = true)
    {
        //Initialization of some necessary variables.
        //==========================================
        int i = int.Parse(theIntAsString);
        // ................
        // .......................
        //==========================================

        if (!doStuff.HasValue || doStuff.Value == true)
           setupStuff(ref _intField,i);
    }

    public Sample(int theInt): this(theInt, false) //"false" param to avoid setupStuff() being called two times
    {
        setupStuff(ref _intField, theInt);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这可能允许第三方通过调用`new Sample(str,false)`来创建Sample而不进行设置. (3认同)

Sun*_*ule 8

构造函数链接,即当您想在一次调用中调用多个构造函数时,您可以将“Base”用于 Is 关系,并将“This”用于同一个类。

  class BaseClass
{
    public BaseClass():this(10)
    {
    }
    public BaseClass(int val)
    {
    }
}
    class Program
    {
        static void Main(string[] args)
        {
            new BaseClass();
            ReadLine();
        }
    }
Run Code Online (Sandbox Code Playgroud)


pas*_*asx 6

下面是一个调用另一个构造函数的示例,然后检查它已设置的属性.

    public SomeClass(int i)
    {
        I = i;
    }

    public SomeClass(SomeOtherClass soc)
        : this(soc.J)
    {
        if (I==0)
        {
            I = DoSomethingHere();
        }
    }
Run Code Online (Sandbox Code Playgroud)


Lin*_*han 5

当从基类继承一个类时,可以通过实例化派生类来调用基类构造函数

class sample
{
    public int x;

    public sample(int value)
    {
        x = value;
    }
}

class der : sample
{
    public int a;
    public int b;

    public der(int value1,int value2) : base(50)
    {
        a = value1;
        b = value2;
    }
}

class run 
{
    public static void Main(string[] args)
    {
        der obj = new der(10,20);

        System.Console.WriteLine(obj.x);
        System.Console.WriteLine(obj.a);
        System.Console.WriteLine(obj.b);
    }
}
Run Code Online (Sandbox Code Playgroud)

示例程序的输出是

50 10 20


您还可以使用this关键字从另一个构造函数调用构造函数

class sample
{
    public int x;

    public sample(int value) 
    {
        x = value;
    }

    public sample(sample obj) : this(obj.x) 
    {
    }
}

class run
{
    public static void Main(string[] args) 
    {
        sample s = new sample(20);
        sample ss = new sample(s);

        System.Console.WriteLine(ss.x);
    }
}
Run Code Online (Sandbox Code Playgroud)

该示例程序的输出是

20


小智 5

是的,您可以在调用基础或此方法之前调用其他方法!

public class MyException : Exception
{
    public MyException(int number) : base(ConvertToString(number)) 
    {
    }

    private static string ConvertToString(int number) 
    { 
      return number.toString()
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 只是为了整体回答-如果您的构造函数应初始化任何只读字段,则不能使用此方法。 (3认同)