📕구조체(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
'C#' 카테고리의 다른 글
[C#]리플렉션(Reflection)과 어트리뷰트(Attribute) (0) | 2022.07.06 |
---|---|
제네릭(Generics)이란? (0) | 2022.06.24 |
생성자 (0) | 2022.06.17 |
프로퍼티(Property, 속성) (0) | 2022.06.14 |
람다 식(Lambda Expression) (0) | 2022.06.12 |