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

时间:2010-10-24 16:06:31

标签: c# constructor

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

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

        _intField = i;
    }

    public Sample(int theInt)
    {
        _intField = theInt;
    }


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

}

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

现在是抓住了:

  1. 我不想复制 设置代码。在这种情况下,只有一个 字段设置但当然可能 不止一个。
  2. 要使字段只读,我需要 从构造函数中设置它们,所以 我无法“提取”共享代码 实用功能。
  3. 我不知道如何打电话 另一个构造函数。
  4. 有什么想法吗?

11 个答案:

答案 0 :(得分:1450)

像这样:

public Sample(string str) : this(int.Parse(str)) {
}

答案 1 :(得分:148)

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

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

    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);
    }
}

答案 2 :(得分:55)

在构造函数体之前,使用:

: base (parameters)

: this (parameters)

示例:

public class People: User
{
   public People (int EmpID) : base (EmpID)
   {
      // Add more statements here.
   }
}

答案 3 :(得分: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);
    }
}

答案 4 :(得分:6)

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

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

    public SomeClass(SomeOtherClass soc)
        : this(soc.J)
    {
        if (I==0)
        {
            I = DoSomethingHere();
        }
    }

答案 5 :(得分:4)

是的,你可以在通话基地之前调用其他方法或者这个!

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

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

}

答案 6 :(得分:1)

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

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);
    }
}

sample program的输出

  

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);
    }
}

sample program的输出为

  

20

答案 7 :(得分:1)

错误处理和使代码可重用是关键。我将字符串添加到int验证中,并且可以根据需要添加其他类型。使用更可重用的解决方案解决此问题的方法可能是:

public class Sample
{
    public Sample(object inputToInt)
    {
        _intField = objectToInt(inputToInt);
    }

    public int IntProperty => _intField;

    private readonly int _intField;
}

public static int objectToInt(object inputToInt)
{
    switch (inputToInt)
        {
            case int inputInt:
                return inputInt;
            break;
            case string inputString:
            if (!int.TryParse(inputString, out int parsedInt))
            {
                throw new InvalidParameterException($"The input {inputString} could not be parsed to string");
            }
            return parsedInt;

            default:
                throw new InvalidParameterException($"Constructor do not support {inputToInt.GetType().Name}");
            break;
        }
}

答案 8 :(得分:0)

构造函数链接,即当您要在一个调用中调用多个构造函数时,可以将“基础”用于“是一种关系”,而将“此”可以用于同一类。

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

答案 9 :(得分:0)

如果您需要在调用另一个构造函数之前而不是之后运行某些东西。

public class Sample
{
    static int preprocess(string theIntAsString)
    {
        return preprocess(int.Parse(theIntAsString));
    }

    static int preprocess(int theIntNeedRounding)
    {
        return theIntNeedRounding/100;
    }

    public Sample(string theIntAsString)
    {
        _intField = preprocess(theIntAsString)
    }

    public Sample(int theIntNeedRounding)
    {
        _intField = preprocess(theIntNeedRounding)
    }

    public int IntProperty  => _intField;

    private readonly int _intField;
}

如果需要设置多个字段,ValueTuple可能会非常有用。

答案 10 :(得分:0)

请,请,而且漂亮,请不要在家里,工作场所或任何真正的地方尝试。

这是解决非常具体问题的一种方法,希望您不要那样。

我发布此消息是因为从技术上来说这是一个答案,也是从另一个角度来看待它。

我重复一遍,请勿在任何情况下使用它。代码将与LINQPad一起运行。

void Main()
{
    (new A(1)).Dump();
    (new B(2, -1)).Dump();
    
    var b2 = new B(2, -1);
    b2.Increment();
    
    b2.Dump();
}

class A 
{
    public readonly int I = 0;
    
    public A(int i)
    {
        I = i;
    }
}

class B: A
{
    public int J;
    public B(int i, int j): base(i)
    {
        J = j;
    }
    
    public B(int i, bool wtf): base(i)
    {
    }
    
    public void Increment()
    {
        int i = I + 1;

        var t = typeof(B).BaseType;
        var ctor = t.GetConstructors().First();
        
        ctor.Invoke(this, new object[] { i });
    }
}

由于构造函数是一种方法,因此可以通过反射进行调用。现在,您可以使用门户网站进行思考,或者将一罐蠕虫的图片可视化。对此感到抱歉。