πŸ’» Programming Language/C#

μŠ€ν„°λ””) λ‘λ²ˆμ§Έ μŠ€ν„°λ”” ν”Όλ“œλ°± 및 질문 μ •λ¦¬λ‚΄μš©

S.Honey 2022. 4. 8. 09:21

sealed ν‚€μ›Œλ“œλ₯Ό λ©”μ†Œλ“œμ— μ‚¬μš©!

  • λΆ€λͺ¨ν΄λž˜μŠ€μ—μ„œ μ˜€μž‘λ™μ„ ν•˜κ²Œλ” ν•˜λŠ” μžμ›μ„ μžμ‹ν΄λž˜μŠ€μ—μ„œ κ±΄λ“œλ¦¬λ©΄ μ•ˆλ˜λŠ” 경우
    • λ©”μ†Œλ“œμ— sealed ν•œμ •μžλ₯Ό μ‚¬μš©ν•΄μ„œ μ œν•œν•  수 μžˆλ‹€.
class Parent
{
    public int num;
    public int count;

    public Parent(int num)
    {
        this.num = num;
        this.count = 0;
        Console.WriteLine("Parent μƒμ„±μž");
    }

    public virtual void addCount() { }
    public void showInfo()
    {
        Console.WriteLine("Num : {0}, Count : {1}", this.num, this.count);
    }
}

class Counter : Parent
{
    public Counter(int num) : base(num)
    {
        Console.WriteLine("Counter μƒμ„±μž");
    }

    public sealed override void addCount()
    {
        base.count++;
    }
}

class Calculator : Counter
{
    public Calculator(int num) : base(num)
    {
        Console.WriteLine("Calculator μƒμ„±μž");
    }

    public void add()
    {
        Console.WriteLine("λ”ν•˜κΈ° 1");
        this.num++;
        base.addCount();
    }
    public void sub()
    {
        Console.WriteLine("λΉΌκΈ° 1");
        this.num--;
        base.addCount();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Parent ncc = new Calculator(10);
        ncc.showInfo();

        Calculator c = (Calculator)ncc;
        c.add();
        c.add();

        c.sub();
        c.sub();
        c.sub();

        c.showInfo();
    }
}
Output

Parent μƒμ„±μž
Counter μƒμ„±μž
Calculator μƒμ„±μž
Num : 10, Count : 0
λ”ν•˜κΈ° 1
λ”ν•˜κΈ° 1
λΉΌκΈ° 1
λΉΌκΈ° 1
λΉΌκΈ° 1
Num : 9, Count : 5
  • μ΅œμƒμœ„ ν΄λž˜μŠ€μ—μ„œ virtual둜 μ •μ˜λœ λ©”μ„œλ“œλ₯Ό μƒμ†λ°›λŠ” ν΄λž˜μŠ€μ—μ„œ sealedν•œμ •μžμ™€ override둜 μ„ μ–Έν•˜κ²Œλ˜λ©΄ κ·Έ 클래슀λ₯Ό μƒμ†λ°›λŠ” ν΄λž˜μŠ€μ—μ„œλŠ” ν•΄λ‹Ή λ©”μ„œλ“œλ₯Ό μž¬μ •μ˜ ν•  수 μ—†λ‹€.
    • νŒŒμƒ ν΄λž˜μŠ€μ—μ„œ μ˜€λ²„λΌμ΄λ“œ ν•  수 μ—†λ‹€.
    • sealed λ©”μ„œλ“œλŠ” κΌ­ overrideμ•žμ—μ„œλ§Œ μ‚¬μš©ν•  수 μžˆλ‹€.
    • sealedλ₯Ό μ“°λ©΄ 상속을 쀄 수 μ—†μœΌλ―€λ‘œ ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ μž¬μ •μ˜ λΆˆκ°€λŠ₯

ν˜•λ³€ν™˜

  • as, () => κΈ°λ³Έ μžλ£Œν˜•μœΌλ‘œ λ³€ν™˜ν–ˆμ„ κ²½μš°μ—λŠ” ? + is

C# κΈ°λ³Έ μžλ£Œν˜• λΆ„λ₯˜
ꡬ뢄 μ„€λͺ…
μ •μˆ˜ ν‘œν˜„ byte, shortm int, long
μ‹€μˆ˜ ν‘œν˜„ float, double
문자 ν‘œν˜„ char
μ°Έ, κ±°μ§“ ν‘œν˜„ boolean

class Human
{
    public void showInfo()
    {
        Console.WriteLine("Human");
    }
}

class Programmer : Human
{
    public void programming()
    {
        Console.WriteLine("개발자");
    }
}

class Program
{
    static void Main(string[] args)
    {

        Human human = new Programmer();
        // as μ—°μ‚°μžλ₯Ό μ΄μš©ν•΄ κΈ°λ³Έ μžλ£Œν˜•μœΌλ‘œ ν˜•λ³€ν™˜

        var aa = human as Programmer;

        if (aa is null) return;

        int? a = human as int;
        var result = human is int; // false
        // as μ—°μ‚°μžλŠ” μ°Έμ‘° ν˜•μ‹ λ˜λŠ” null ν—ˆμš© ν˜•μ‹κ³Ό ν•¨κ»˜ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. 'int'은(λŠ”) null을 ν—ˆμš©ν•˜μ§€ μ•ŠλŠ” κ°’ ν˜•μ‹μž…λ‹ˆλ‹€.

        string? str = human as string;
        // μ°Έμ‘° λ³€ν™˜, boxing λ³€ν™˜, unboxing λ³€ν™˜, λž˜ν•‘ λ³€ν™˜ λ˜λŠ” null ν˜•μ‹ λ³€ν™˜μ„ 톡해 'AsisEx.Human' ν˜•μ‹μ„ 'string'(으)둜 λ³€ν™˜ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
        // =>`as`μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•œ λ³€ν™˜μ€ 상속, μ°Έμ‘° λ³€ν™˜ 및 boxing λ³€ν™˜μ—μ„œ ν—ˆμš©

        int x = (int)human;
        // => 'Human' ν˜•μ‹μ„ 'int' ν˜•μ‹μœΌλ‘œ λ³€ν™˜ν•  수 μ—†μŠ΅λ‹ˆλ‹€.    
        // double y = (double)human; // => 'Human' ν˜•μ‹μ„ 'double' ν˜•μ‹μœΌλ‘œ λ³€ν™˜ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
        // string str2 = (string)human; // => 'Human' ν˜•μ‹μ„ 'string' ν˜•μ‹μœΌλ‘œ λ³€ν™˜ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

        Console.WriteLine(human is int);
        Console.WriteLine(human is double);
        Console.WriteLine(human is string);
    }
}
Output

False
False
False
  • μ°Έμ‘°ν˜•μ€ κΈ°λ³Έμžλ£Œν˜•μœΌλ‘œ λ³€ν™˜μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€.(as 및 κ°•μ œν˜•λ³€ν™˜ λ‘˜λ‹€ μ•ˆλ¨(()μ‚¬μš©)) => C# μžμ²΄μ—μ„œ 막고 있음
  • isλ₯Ό μ‚¬μš©ν•˜λŠ”κ²ƒμ€ ν˜•λ³€ν™˜μ΄ μ•„λ‹Œ bool νƒ€μž…μ˜ λ°˜ν™˜ 값을 톡해 체크λ₯Ό ν•˜λŠ”κ²ƒμ΄κΈ°μ— μ‚¬μš©κ°€λŠ₯
  • string의 경우 μ°Έμ‘°ν˜•μ΄μ§€λ§Œ κΈ°λ³Έμžλ£Œν˜•μ²˜λŸΌ C#μ—μ„œ λ§‰κ³ μžˆλŠ”λ“―ν•¨.

μ΄ˆκΈ°ν™”λœ 객체와 μ΄ˆκΈ°ν™”λ˜μ§€ μ•Šμ€ 객체λ₯Ό μž„μ˜μ˜ λ©”μ†Œλ“œμ— λ§€κ°œλ³€μˆ˜λ‘œ λ„˜κ²Όμ„ λ•Œ λ™μž‘ν™•μΈ

class MyField
{
    public int field1;
    public int field2;
}

class AssignRefType
{
    static void Main(string[] args)
    {
        MyField? mf1 = null;
        MyField mf2 = new MyField() { field1 = 1, field2 = 2 };

        Test(mf1);
        Test(mf2);

        //Console.WriteLine("mf1 => field1 : {0} field2 : {1} ", mf1.field1, mf1.field2); => error
        //Console.WriteLine("mf2 => field1 : {0} field2 : {1} ", mf2.field1, mf2.field2);

        TestRef(ref mf1);
        TestRef(ref mf2);

        Console.WriteLine("mf1 => field1 : {0} field2 : {1} ", mf1.field1, mf1.field2);
        Console.WriteLine("mf2 => field1 : {0} field2 : {1} ", mf2.field1, mf2.field2);
    }

    private static void Test(MyField param)
    {
        if (param is null) param = new MyField();

        param.field1 = 3;
        param.field2 = 4;
    }

    private static void TestRef(ref MyField param)
    {
        if (param is null) param = new MyField();

        param.field1 = 3;
        param.field2 = 4;
    }
}
Output

mf1 => field1 : 3 field2 : 4
mf2 => field1 : 3 field2 : 4
  • mf1의 경우 stackλ©”λͺ¨λ¦¬μ—μ„œ null을 κ°€μ§€κ³  heap에 λ©”λͺ¨λ¦¬κ°€ ν• λ‹Ήλ˜μ–΄μžˆμ§€ μ•Šλ‹€. C#은 기본적으둜 Call by Value이기 λ•Œλ¬Έμ— null을 λ©”μ†Œλ“œλ‘œ λ„˜κ²¨μ£Όκ²Œ 되고 μ§€μ—­μΈμŠ€ν„΄μŠ€λ‘œ ν™œμš©λ˜λ˜ param이 λ‚΄λΆ€μ—μ„œλ§Œ λ‘œμ§μ„ μˆ˜ν–‰ν•˜κ³  후에 μΈμŠ€ν„΄μŠ€κ°€ μ‚­μ œλ˜κΈ° λ•Œλ¬Έμ— κ²°κ΅­ mf1은 κ·ΈλŒ€λ‘œ null을 κ°€μ§€κ²Œ λœλ‹€.

λ‹€ν˜•μ„± 확인 예제 μΆ”κ°€

class A{
    public virtual void Print1()
    {
        Console.WriteLine("A : Print1");
    }

    public void Print2()
    {
        Console.WriteLine("A : Print2");
    }
}

class A1 : A
{
    public override void Print1()
    {
        Console.WriteLine("A1 : Print1");
    }

    public void Print2()
    {
        Console.WriteLine("A1 : Print2");
    }
}

class A2 : A
{
    public override void Print1()
    {
        Console.WriteLine("A2 : Print1");
    }

    public void Print2()
    {
        Console.WriteLine("A2 : Print2");
    }
}

class A3 : A
{
    public override void Print1()
    {
        Console.WriteLine("A3 : Print1");
    }

    public void Print2()
    {
        Console.WriteLine("A3 : Print2");
    }
}

class App
{
    static void Main(string[] args)
    {
        A[] arr = new A[]
        {
            new A1(),
            new A2(),
            new A3()
        };

        foreach (var a in arr)
        {
            a.Print1();
            a.Print2();
        }

    }
}
Output

A1 : Print1
A : Print2
A2 : Print1
A : Print2
A3 : Print1
A : Print2
  • A의 μžλ£Œν˜•μœΌλ‘œ A1, A2, A3 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν–ˆμ„λ•Œ Aμ—μ„œλŠ” μžμ‹ 클래슀의 λ©”μ†Œλ“œλ₯Ό μ°Έμ‘°ν•  수 μ—†μœΌλ‚˜, override ν‚€μ›Œλ“œλ₯Ό μ΄μš©ν•΄μ„œ μž¬μ •μ˜ 된 λ©”μ†Œλ“œμ˜ 경우 μžμ‹λ©”μ†Œλ“œμ˜ 결과둜 좜λ ₯이 λœλ‹€.
  • 즉 override에 μ˜ν•΄ μž¬μ •μ˜λœ λ©”μ†Œλ“œλŠ” λΆ€λͺ¨ν΄λž˜μŠ€ν˜•μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό μžμ‹ν΄λž˜μŠ€ν˜•μ˜ μΈμŠ€ν„΄μŠ€λ‘œ μ„ μ–Έν–ˆμ„λ•Œ μž¬μ •μ˜λœ ν˜•νƒœλ‘œ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.

struct의 크기가 일정크기λ₯Ό λ„˜μ–΄κ°€λ©΄ value type이 μ•„λ‹Œ ref type => Stack Overflow


λ©”λͺ¨λ¦¬μ ˆμ•½μ€ 클래슀, μ†λ„λŠ” ꡬ쑰체

  • μΈμŠ€ν„΄μŠ€ν•œλ‹€λ©΄ κ°€λΉ„μ§€ μ»¬λ ‰μ…˜(속도)
    • κ΅¬μ‘°μ²΄λŠ” μŠ€νƒμ— λ°”λ‘œ ν• λ‹Ήλ˜κΈ° λ•Œλ¬Έμ— κ°€λ°”μ§€μ»¬λ ‰μ…˜μ΄ λ°œμƒ ν•˜μ§€ μ•ŠμŒ
    • ν΄λž˜μŠ€λŠ” μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 λ•Œ λ§ˆλ‹€ νž™μ— λ©”λͺ¨λ¦¬ ν• λ‹Ήν•˜κΈ° λ•Œλ¬Έμ— 값을 νκΈ°ν•˜κΈ° μœ„ν•΄μ„œλŠ” κ°€λ°”μ§€μ»¬λ ‰μ…˜μ΄ ν•„μš”.

  • λ§Žμ€ μ–‘μ˜ λ³€μˆ˜λ₯Ό κ°€μ§€κ³  μžˆλŠ” κ΅¬μ‘°μ²΄λŠ” NO(λ©”λͺ¨λ¦¬)
    • μ°Έμ‘°ν˜•μ‹μΈ ν΄λž˜μŠ€λŠ” 값듀을 κ°€λ¦¬ν‚€λŠ” μ£Όμ†Œλ§Œ μŠ€νƒμ— μ €μž₯ν•˜μ§€λ§Œ κ΅¬μ‘°μ²΄λŠ” κ°€μ§€κ³ μžˆλŠ” λ³€μˆ˜λ“€μ˜ 값듀을 λͺ¨λ‘ μŠ€νƒμ— μ €μž₯ν•˜κΈ° λ•Œλ¬Έμ— κ·Έ 크기만큼 μŠ€νƒμ˜ μœ„μΉ˜ μ—­μ‹œ μ»€μ§€κ²Œ 됨. ν•˜μ§€λ§Œ μŠ€νƒμ€ 크기가 μ œν•œμ μ΄κΈ° λ•Œλ¬Έμ— λ„ˆλ¬΄ λ§Žμ€ 양을 κ°€μ§€κ²Œ 되면 μŠ€νƒ μ˜€λ²„ν”Œλ‘œμš°κ°€ λ°œμƒν•  수 μžˆλŠ” μœ„ν—˜μ΄ μžˆλ‹€. => νž™λ©”λͺ¨λ¦¬ μΉ¨λ²”

  • κ΅¬μ‘°μ²΄λŠ” μ–Έμ œ μ‚¬μš©ν• κΉŒ?
    • λ³€μˆ˜μ˜ 크기가 μž‘κ±°λ‚˜, 수λͺ…이 μ§§κ³ , 자주 ν• λ‹Ήλ˜λŠ” κ°μ²΄λŠ” ꡬ쑰체둜 λ§Œλ“€μ–΄ μ£ΌλŠ”κ²Œ μ’‹μŒ.