C언어를 주로 사용하더 나에게는 이 Class 라는 것이 이해하기 쉬우면서도 이해하기 어려운 부분이었다.

흔히 Class와 Sturct(구조체)를 비교하는데 Struct는 평소에 아주 많이 사용하는 놈이기 때문이었다.

 

C에서의 구조체의 정의는 너무도 쉽다. 

함께 쓰고 싶은 다양한 데이터 Type 변수들의 집합. 모음. 모둠..? 

그리고 OOP를 흉내낼 수 있도록 해준 '함수 포인터'도 멤버로 가질 수 있다. (C#에서는 함수를 가질수 있다는 점이 가장 큰 차이점일까.)

 

구조체와 클래스의 차이점에 대해 정리되어 있는 것은 이보다 더 많은 자료들을 찾아볼 수 있다.

구분 구조체 (STRUCT) 객체 (CLASS)
형식 Value (값 형식) Reference (참조 형식)
생성영역 Stack Heap
인스턴스 new () 선언
상속 X O
생성자 X O
인터페이스 O O
STATIC X O

 


 

구조체의 경우 구조체 배열을 사용하여 동일한 형태의 여러 데이터들의 집합을 관리할 수 있다. 

이 기능은 프로그램 내의 데이터 관리 측면에 있어서 엄청난 효율성을 가져다 준다. 

 

게다가 배열이다. Index를 사용해서 가장 빠른 속도로 원하는 데이터에 접근할 수 있으니, 개발자의 입장에서는 최고의 조합이다. C#의 클래스도 같은 구조의 기능을 지원할까.

 

 

나는 아래와 같이 객체 배열을 만들어서 사용하고 싶었다. 

 

 

제작중인 자동매매 프로그램의 '종목'관련 Class 상속 관계

 

 

부모 클래스의 변수 및 함수를 상속받은 자식이 사용하도록, 그것도 외부 클래스에서 사용하도록 하기 위해 부모클래스의 변수에 대해 '접근 제한자'를 사용하도록 하는 데에도 몇번의 시행착오를 겪었다. 

 

부모 클래스의 변수를 상속받은 자식 클래스에서만 접근이 가능하도록 'protected'로 선언하였는데 아래 표의 설명이 많은 도움이 되었다.

 

 C# 접근 제한자
public
클래스의 내부와 외부 모든 곳에서 접근이 가능하다.
protected
클래스의 내부와 해당 클래스를 상속 받은 자식 클래스에서만 접근이 가능하다.
private
해당 클래스 내부에서만 접근이 가능하다.

 

 

그리고 외부 클래스에서 자식 클래스인 Stock_RTB를 객체 배열로 선언하여 사용하기 위해 C# 기초 책과 많은 포스팅에서 아래와 같이 간단하게 적용했는데....

이상하게 계속 NullReference Exception이 발생하는 것이다. 

using System;

namespace Program
{
	public partial class MainClass : Form
    {
    	... 생략 ...
        
        // RTB 클래스 배열 선언
        Stock_Realtime_Balance[] gArrStockRTB;
        
        
        ... 생략 ...
        
        string hname = "이베스트증권";
        
        gArrStockRTB = new Stock_Realtime_Balance[3];
        
        for (int index = 0; index < 3; i++)
        {
            try
            {
                gArrStockRTB[index].setCodeName(hname);
                ... 생략 ...
                
                string line = String.Format("{0}", gArrStockRTB[index].getCodeName());
                ... 생략 ...
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e);
            }
        }
         ... 생략 ...
    }
}               
                

와...정말 온갖 부분을 다 예외 처리하고 로그를 찍어서 확인해 봤지만 도저히 찾지를 못했는데, 2일만에 드디어 문제가 됐던 부분을 찾았다. (2일이라면 오래 걸린것 같지만...이 프로그램을 만드는데에 하루에 1.5시간 정도만 투자하고 있으므로 생각보다 빨리 찾은 셈이다.)

using System;

namespace Program
{
	public partial class MainClass : Form
    {
    	... 생략 ...
        
        // RTB 클래스 배열 선언
        Stock_Realtime_Balance[] gArrStockRTB;
        
        
        ... 생략 ...
        
        string hname = "이베스트증권";
        
        gArrStockRTB = new Stock_Realtime_Balance[3];
        for (int i = 0; i < gArrStockRTB.Length; i++)
            gArrStockRTB[i] = new Stock_Realtime_Balance();
        
        for (int index = 0; index < 3; i++)
        {
        	try
        	{
        		gArrStockRTB[index].setCodeName(hname);
                ... 생략 ...
                
                string line = String.Format("{0}", gArrStockRTB[index].getCodeName());
                ... 생략 ...
            }
            catch (NullReferenceException e)
            {
                Console.WriteLine(e);
            }
        }
         ... 생략 ...
    }
}

다시 각 객체 배열의 위치마다 new로 잡아줘야 한다니...객체(Class)의 특성상 당연한 작업인데...

좀 더 세련되게 'Extension Method'를 사용해서 심플하게 처리하는 방법이 있다는데...C# 초보자인 나는 일단 for문을 사용하기로 했다....

 

역시 정확하게 다 이해하지 못한 상황에서 개발부터 진행하면 이렇게 간단한 실수를 하게된다.

프로그래밍은 재밌다.

 

 

Posted by [ 브랜든 ]
,