code

다른 생성자에서 하나의 생성자 호출

codestyles 2020. 9. 28. 09:08
반응형

다른 생성자에서 하나의 생성자 호출


읽기 전용 필드에 값을 제공하는 두 개의 생성자가 있습니다.

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

한 생성자는 값을 직접 수신하고 다른 생성자는 일부 계산을 수행하고 값을 얻은 다음 필드를 설정합니다.

이제 여기에 문제가 있습니다.

  1. 설정 코드를 복제하고 싶지 않습니다. 이 경우 하나의 필드 만 설정되지만 물론 둘 이상의 필드가있을 수 있습니다.
  2. 필드를 읽기 전용으로 만들려면 생성자에서 필드를 설정해야하므로 공유 코드를 유틸리티 함수로 "추출"할 수 없습니다.
  3. 하나의 생성자를 다른 생성자에서 호출하는 방법을 모르겠습니다.

어떤 아이디어?


이렇게 :

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

자체 메서드에서 초기화하지 않고 원하는 것을 만족스럽게 달성 할 수없는 경우 (예 : 초기화 코드 이전에 너무 많은 작업을 수행하거나 try-finally로 래핑하거나 무엇이든간에) 일부 또는 전부를 가질 수 있습니다. 생성자는 초기화 루틴을 참조하여 읽기 전용 변수를 전달하며, 그러면 원하는대로 조작 할 수 있습니다.

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

생성자의 본문 앞에 다음 중 하나를 사용하십시오.

: base (parameters)

: this (parameters)

예:

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

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

다음은 다른 생성자를 호출 한 다음 설정 한 속성을 확인하는 예제입니다.

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

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

예, 콜베이스 또는이 전에 다른 메서드를 호출 할 수 있습니다!

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

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

}

기본 클래스에서 클래스를 상속 할 때 파생 클래스를 인스턴스화하여 기본 클래스 생성자를 호출 할 수 있습니다.

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

의 출력 샘플 프로그램 입니다

50 10 20


You can also use this keyword to invoke a constructor from another constructor

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

The output of this sample program is

20


Constructor chaining i.e you can use "Base" for Is a relationship and "This" you can use for same class, when you want call multiple Constructor in single call.

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

Error handling and making your code reusable is key. I added string to int validation and it is possible to add other types if needed. Solving this problem with a more reusable solution could be this:

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

참고URL : https://stackoverflow.com/questions/4009013/call-one-constructor-from-another

반응형