C#

구조체(Struct)와 클래스(Class)

기리도 2022. 6. 17. 15:13
728x90

📕구조체(Struct)


📖구조체란?

C#에서 구조체란 데이터와 관련된 기능을 캡슐화한 값 형식으로, 생성자, 상수, 필드, 메서드, 프로퍼티, 인덱서, 연산자, 이벤트를 포함할 수 있다. 일반적으로 동작을 구현하기보다는 필드나 상수 같은 데이터를 관리하는 용도로 쓰인다.

📌구조체의 선언

구조체를 선언할 때는 struct 키워드를 사용한다. 구조체의 모든 필드는 대입 연산자 혹은 생성자를 통해 값을 초기화해 주어야 한다. 초기화되지 않은 필드가 있을 시 컴파일 에러가 발생한다. 아래 코드에서는 기본 생성자를 통해 필드를 초기화했다.

struct Coordinate
{
    public int x;
    public int y;
}

class Program
{
  static void Main(string[] args)
  {
   Coordinate point = new Coordinate();
   Console.WriteLine(point.x); //output: 0  
   Console.WriteLine(point.y); //output: 0
  }
}

Coordinate point = new Coordinate()로 기본 생성자를 호출한 뒤 Console.WriteLine(point.x) Console.WriteLine(point.y)를 호출했기 때문에 위 코드에서는 컴파일 에러가 발생하지 않는다.

다음은 생성자를 호출하지 않고 구조체 필드를 초기화한 경우이다.

struct Coordinate
{
    public int x;
    public int y;
}

class Program
{
  static void Main(string[] args)
  {
   Coordinate point;
   //Console.Write(point.x);
   
   point.x = 10;
   point.y = 20;
   Console.Write(point.x); //output: 10  
   Console.Write(point.y); //output: 20
  }
}

위 코드에서는 생성자를 호출하지 않고 대입 연산자를 통해 멤버를 초기화했다(point.x = 10, point.y = 20). 따라서 컴파일에러가 발생하지 않는다. 그러나 주석 처리한 Console.Write(point.x)의 경우 멤버를 초기화하기 전에 호출되므로 주석을 해제하면 컴파일 에러를 일으킨다.

💡C# 9.0까지는 구조체의 생성자는 정적이거나 매개 변수가 반드시 있어야 했지만 C# 10부터는 기본 생성자 및 매개 변수가 없는 생성자도 사용할 수 있다.

📌메서드와 프로퍼티를 포함한 구조체

struct Coordinate
{
    public int x { get; set; }
    public int y { get; set; }

    public void SetOrigin()
    {
        this.x = 0;
        this.y = 0;
    }
}

class Program
{
  static void Main(string[] args)
  {
   Coordinate point = new Coordinate();
   point.SetOrigin();
   Console.WriteLine(point.x); //output: 0  
   Console.WriteLine(point.y); //output: 0
  }
}

📌구조체로 이벤트 정의하기

struct Coordinate
{
    private int _x, _y;

    public int x 
    {
        get{
            return _x;
        }

        set{
            _x = value;
            CoordinatesChanged(_x);
        }
    }

    public int y
    {
        get{
            return _y;
        }

        set{
            _y = value;
            CoordinatesChanged(_y);
        }
    }

    public event Action<int> CoordinatesChanged;
}

CoordinatesChanged 이벤트를 구조체 내에 선언했다. CoordinatesChanged 이벤트는 x나 y 프로퍼티가 호출될 때 등록된 이벤트 핸들러를 호출한다. 다음은 이벤트 핸들러를 호출하는 코드이다.

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

        Coordinate point = new Coordinate();
        
        point.CoordinatesChanged += StructEventHandler;
        point.x = 10;
        point.y = 20;
    }

    static void StructEventHandler(int point)
    {
        Console.WriteLine("Coordinate changed to {0}", point);
    }
}

 

 


📕클래스(Class)


📖클래스란?

클래스란 C#이 제공하는 참조 형식 중 하나다. 객체 지향의 관점에서 클래스는 객체의 동작과 기능을 정의하는 핵심적인 역할을 한다. 생성자, 상수, 필드, 메서드, 프로퍼티, 인덱서, 연산자, 이벤트를 멤버로 둔다는 점이 구조체와 비슷하지만 구조체와 달리 클래스는 다형성 및 상속을 지원한다. 때문에 C#에서는 클래스의 사용 빈도가 압도적으로 높다.

📌클래스의 선언

클래스의 기본 형식은 다음과 같다.

👉[ 접근 한정자 ] [ class ] [ 이름 ] [ 중괄호 ]

//[access modifier] - [class] - [identifier]
public class Customer
{
   // Fields, properties, methods and events go here...
}

클래스는 참조 형식이므로 클래스에 접근하려면 new 키워드로 객체를 할당해야 한다.

public class Customer
{
   public void Test()
   {
   	Console.WriteLine("참조 성공");
   }
}

class TestClass
{    
    static void Main()
    {
    	Customer object1 = new Customer();
        object1.Test();
    }
}

object1라는 이름으로 Customer 클래스의 변수를 선언하고 객체를 할당했다. object1.Test()를 실행하면 정상적으로 글자가 출력되는 걸 확인할 수 있다.

클래스에 객체를 할당할 때 객체를 새로 생성하지 않고 이전에 생성한 객체를 할당하는 것도 가능하다.

public class Customer
{
   public void Test()
   {
   	Console.WriteLine("참조 성공");
   }
}

class TestClass
{    
    static void Main()
    {
    	Customer object1 = new Customer();
        Customer object2 = object1;
        object2.Test();
    }
}

위 코드에서 object1 object2는 같은 객체를 참조한다. 따라서 object2.Test()를 실행하면 정상적으로 글자가 출력된다.

반면 아래처럼은 사용할 수 없다.

public class Customer
{
   public void Test()
   {
   	Console.WriteLine("참조 성공");
   }
}

class TestClass
{    
    static void Main()
    {
    	Customer object1;
        object1.Test();
    }
}

 

📖중첩 클래스

중첩 클래스란 클래스 내에 선언된 클래스를 말한다.

class OuterClass {
  ...
  class InnerClass {
    ...
  }
}

OuterClass 클래스 내에 중첩 클래스 InnerClass를 선언했다. 중첩 클래스에 접근하려면 중첩 클래스와 중첩 클래스를 선언한 클래스의 객체를 각각 생성해야 한다. 위 코드에서 OuterClass의 객체는 'new OuterClass()'로 곧바로 생성할 수 있지만 InnerClass의 객체는 OuterClass의 객체를 통해서만 생성할 수 있다.

OuterClass.InnerClass obj2 = new OuterClass.InnerClass();

샘플 코드로 자세히 살펴 보자.

using System;
namespace CsharpNestedClass {
 
  // outer class
  public class Car {

    public void displayCar() {
      Console.WriteLine("Car: Bugatti");
    }
 
    // inner class
    public class Engine {
      public void displayEngine() {
        Console.WriteLine("Engine: Petrol Engine");
      }
    }
  }
  class Program {
    static void Main(string[] args) {

      // create object of outer class
      Car sportsCar = new Car();

      // access method of outer class
      sportsCar.displayCar();
 
      // create object of inner class
      Car.Engine petrolEngine = new Car.Engine();
      
      // access member of inner class
      petrolEngine.displayEngine();
 
      Console.ReadLine();
    }
  }
}

실행 결과:

Car: Bugatti
Engine: Petrol Engine

Car 클래스 내에 Engine 클래스를 선언했다. 두 클래스는 각각 displayCar()displayEngine() 메서드를 포함하며, Program 클래스에서 두 메서드를 호출했다. 위 코드에서 알 수 있는 건 두 클래스에 접근하는 방법이 다르다는 것이다.

  • Car : sportsCar.displayCar()
  • Engine : petrolEngine.displayEngine()

만약 다음과 같은 방법으로 displayEngine()을 호출하려고 하면 오류가 발생한다.

sportsCar.displayEngine();

📖상속

상속은 다형성 및 캡슐화와 함께 객체 지향 프로그램의 핵심 기능이다. 상속은 이름 그대로 '물려받음'을 의미하며, 구체적으로는 다른 클래스의 멤버(생성자 제외)를 물려받는 것을 뜻한다. 상속을 이용하면 다른 클래스의 멤버를 직접 구현하지 않고도 재사용할 수 있어서 코드가 간결해진다.

이때 멤버를 물려주는 클래스와 물려받는 클래스를 각각 기본 클래스, 파생 클래스라 부르며, 기본 클래스는 여러 파생 클래스에게 상속될 수 있지만 파생 클래스의 기본 클래스는 오직 하나여야 한다.

💡 기본 클래스와 파생 클래스를 다른 말로 부모 클래스와 자식 클래스라고도 한다.

📌사용

클래스를 상속할 때는  : 기호를 사용한다.

using System;

namespace Inheritance {

  // base class
  class Animal { 

    public string name;

    public void display() {
      Console.WriteLine("I am an animal");
    }
  } 
  
  // derived class of Animal 
  class Dog : Animal {
    
    public void getName() {
      Console.WriteLine("My name is " + name);
    }
  }

  class Program {

    static void Main(string[] args) {

      // object of derived class
      Dog labrador = new Dog();

      // access field and method of base class
      labrador.name = "Rohu";
      labrador.display();

      // access method from own class
      labrador.getName();

      Console.ReadLine();
    }
  }
}

위 코드에서 파생 클래스는 Dog 클래스이고 기본 클래스는 Animal 클래스이다. Dog 클래스에는 name display()가 구현되어 있지 않지만 Animal 클래스를 상속받았기에 해당 멤버를 사용할 수 있다. 물론 Dog 클래스에 직접 정의된 getName() 메서드도 정상적으로 작동한다.

실행 결과는 다음과 같다.

I am an animal
My name is Rohu

📌protected 멤버

접근 한정자 protected로 정의된 멤버는 클래스 내부와 파생 클래스에서만 접근할 수 있다.

using System;

namespace Inheritance {

  // base class
  class Animal { 
    protected void eat() {
      Console.WriteLine("I can eat");
    }
  } 
  
  // derived class of Animal 
  class Dog : Animal {
     static void Main(string[] args) {

      Dog labrador = new Dog();

      // access protected method from base class
      labrador.eat();

      Console.ReadLine();
    }
  }
}

실행 결과:

I can eat

 

 


🔖인용 및 참고

https://www.tutorialsteacher.com/csharp/csharp-struct

 

Struct in C#

C# - Struct Updated on: June 25, 2020 In C#, struct is the value type data type that represents data structures. It can contain a parameterized constructor, static constructor, constants, fields, methods, properties, indexers, operators, events, and nested

www.tutorialsteacher.com

https://docs.microsoft.com/ko-kr/dotnet/csharp/language-reference/builtin-types/struct

 

구조체 형식 - C# 참조

C#의 구조체 형식에 관한 자세한 정보

docs.microsoft.com

https://www.programiz.com/csharp-programming/inheritance

 

C# Inheritance (With Examples)

In C#, inheritance allows us to create a new class from an existing class. It is a key feature of Object-Oriented Programming (OOP). The class from which a new class is created is known as the base class (parent or superclass). And, the new class is called

www.programiz.com

https://docs.microsoft.com/ko-kr/dotnet/csharp/fundamentals/types/classes

 

클래스

클래스 형식 및 이를 만드는 방법을 자세히 알아봅니다.

docs.microsoft.com

 

728x90