변수란?
우선 변수의 개념부터 알아봅시다. C#에서 변수는 어떤 값의 저장 위치를 나타냅니다. 그리고 모든 변수들은 type을 가지는데, type이란 변수에 어떤 값을 저장할 수 있는지를 나타냅니다.
변수를 프로그래머가 사용할 수 있도록 하려면 총 2가지의 과정을 거쳐야 합니다.
- 선언(Declaring) : 변수의 type과 이름을 작성.
- 초기화(Initializing) : 변수의 값을 "최초로 할당"하는 작업을 초기화라고 합니다.
int testVar; // 선언
testVar = 123; // 초기화
위 2가지 과정을 한 번에 이루어내려면 다음과 같이 선언 및 초기화 작업을 해주면됩니다.
int testVar = 123; // 선언 및 초기화
이로써 기초적인 변수의 사용법은 알게되었지만 변수의 선언에 대해 조금 더 자세히 살펴봅시다.
변수의 명시적 선언과 암시적 선언
class A
{
// 1. 명시적 변수 선언(Explicitly typed)
int num;
string name;
float percent;
double precisePercent;
B bInstance;
public void TestMethod()
{
// 2. 암시적 지역 변수 선언(Implicitly typed)
var a = 3; // 자동으로 int형으로 인식함
var city = "Busan"; // 자동으로 string형으로 인식함
}
}
class B { }
명시적 변수 선언
변수를 선언할 때 타입을 명시적으로 작성하는 것과 암시적으로 작성하는 방법이 나뉩니다. 명시적으로 작성한다는 것은 말 그대로 int
, string
, float
와 같은 키워드를 사용하는 것이고, 암시적으로 타입을 적어주는 것은 var
이라는 키워드를 사용합니다.
암시적 변수 선언
암시적 변수선언이란 것은 var키워드를 사용한 변수 선언 방식입니다. 이것은 초기화 문의 오른쪽에 있는 식에서 변수의 형식을 유추하도록 컴파일러에 지시합니다. 유추된 형식은 기본 제공 타입(built-in type), 무명 타입(anonymous type), 사용자 정의 형식(user-defined type)또는 .NET 클래스 라이브러리에 정의된 타입일 수 있습니다. 여기서는 built-in type의 선언만 사용해보았습니다.
var키워드에 마우스를 올려보면 자동으로 System.Int32으로 인식하는 것을 확인할 수 있습니다. 즉, int타입으로 인식합니다. (System.Int32가 왜 int타입인지는 .NetFramework의 데이터타입과 구조를 알면 알 수 있습니다.)
타입 종류에 대한 간략한 예시
- 기본 제공 타입(built-in type): int, string, float, etc...
- anonymous type:
var anoyVar = new { Name="김길동", Age=19 };
- 사용자 정의 형식(user-defined type): 사용자가 정의한 클래스를 의미. 사용자가 정의한 클래스 및 인터페이스는 타입으로 사용될 수 있다.
- .NET Framework Class Library: = System.Diagnostics, System.IO,
anonymous type 변수를 선언할 때는 특정 타입이 없기 때문에 var로 선언한다.
변수를 var로 선언할 때의 특징
- var 키워드는 지역 변수를 선언할 때 밖에 사용하지 못합니다.
- 변수 선언과 동시에 반드시 초기화 되어야 합니다.
- 함수의 리턴 타입, 파라미터로는 사용할 수 없습니다.
필드 변수와 지역 변수의 값 할당에 대한 차이.
지역 변수는 기본값을 할당받지 못하기 때문에 반드시 사용 전에 값을 할당해야 합니다. 그러나 필드 변수는 값을 할당하지 않으면, 해당 타입의 기본값이 자동으로 할당됩니다. 예를 들어, int 타입의 필드인 경우 기본값 0 이 할당됩니다. 그래서 위 코드의 변수 x와 y는 자동으로 0이 할당되게 됩니다.
Default values
다음 변수의 종류들은 각자의 type이 가진 default value로 자동 초기화됩니다.
- static 변수
- 클래스 instnace의 변수
- Array elements
변수의 default value는 변수의 type에 영향을 받습니다. 그리고 이것은 다음 내용에 의해 결정됩니다.
- value type 변수의 경우 기본값은 value_type의 기본 생성자에서 계산한 값과 동일합니다.
- reference_type 변수의 경우 기본값은 null입니다.
- pointer_type의 경우 기본값은 null입니다.
정말 대부분의 경우 value type과 reference type만 신경쓰면 됩니다.
변수의 종류
class A
{
public static int x; // 정적 필드 변수
int y; // 인스턴스 필드 변수
void F(int[] v, int a, ref int b, out int c)
{
int i = 1; // 지역변수: 할당이 없으면 오류 발생.
c = a + b++;
}
}
x
: 정적 필드 변수 (static)y
: 인스턴스 필드 변수v[0]
: 배열의 요소a
: value 매개변수b
: reference 매개변수c
: output 매개변수i
: 지역 변수
(우선 정적 필드 변수와 인스턴스 필드변수, 지역 변수만 다룹니다.)
정적 변수
public static int x
처럼 static modifier(제한자)가 붙은 변수입니다.
정적 변수의 초기 값은 변수 type의 기본값입니다.
C#의 static은 처음부터 로드되지 않으며, 그 static 타입이 처음으로 사용될 때 초기화됩니다. 예를 들어, 아래와 같은 타입 A가 있을 경우, 프로그램이 실행된 후, 만약 누군가 A 클래스를 처음 사용하면, id가 초기화됩니다.
class A
{
static int id = 1;
string name = "A";
}
스태틱 변수는 클래스에 처음 접근하는 순간 초기화됩니다. 일반적으로 변수들이 객체가 새로 생성될 때 메모리가 초기화 되는 것과 다르게, A클래스의 객체를 생성함과 관계 없이 단 하나의 스태틱 변수의 메모리가 유지 된다는 특징이 있습니다. 즉, 프로그램 시작에서 한 번의 메모리 할당이 수행되면 프로그램의 끝까지 그 메모리를 유지시킵니다. 그래서 C# 프로그램을 제작할 때 프로그램을 통틀어서 "단 하나의 유일한 변수"를 선언하고 싶을 때 사용합니다.
https://stackoverflow.com/questions/3965976/when-do-static-variables-get-initialized-in-c
modifier(제한자)라는 뜻에 대하여
modifier는 한국으로 번역되어 들어오면서 한정자, 제한자로 번역되어 들어왔지만, 이보다 그냥 modifier자체의 뜻인 "수식어"정도가 이해하기 편할 것 같기도 하다.
Instance variables
General
일반적으로는 static 제한자 없이 선언된 변수를 보고 instance 변수라고 합니다.
클래스의 instance 변수
클래스의 instance 변수는 해당 클래스의 새 인스턴스(객체)가 생성될 때 존재하는 상태가 됩니다. 만약 참조가 없고 인스턴스의 finalizer가 실행되면 인스턴스의 변수는 존재하지 않게 됩니다.
finalizer에 대하여
finalizer(종료자)는 과거에 destructors(소멸자)라고 불렸습니다. 이것은 가비지 컬렉터로 클래스의 인스턴스를 수집할 때 필요한 최종 정리(final clean-up)를 할 때 호출됩니다. 보통의 경우에는 System.Runtime.InteropServices.SafeHandle 덕분에 프로그래머가 종료자를 작성할 필요가 거의 없습니다. (클래스 내부에 Unmanaged Resource 가 없다면 Finalizer 를 구현할 필요가 없습니다.)
finalizer 예시
class Car
{
~Car() // finalizer
{
// cleanup statements...
}
}
클래스의 instance 변수의 초기값
위에서도 얘기했었지만, 클래스의 instance 변수의 초기 값은 변수 type의 기본값입니다. definite-assignment checking(명확한 할당을 체킹)을 하기 위해 클래스의 instance 변수는 초기에 할당된 것으로 간주합니다. C#은 컴파일 타임에 초기화되지 않은 변수를 감지하고 오류를 반환합니다. (C++은 초기화되지 않은 변수에 접근가능.)
definite-assignment에 대한 내용은 밑에 기재해놓았습니다.
구조체의 instance 변수
An instance variable of a struct has exactly the same lifetime as the struct variable to which it belongs. In other words, when a variable of a struct type comes into existence or ceases to exist, so too do the instance variables of the struct. The initial assignment state of an instance variable of a struct is the same as that of the containing struct variable. In other words, when a struct variable is considered initially assigned, so too are its instance variables, and when a struct variable is considered initially unassigned, its instance variables are likewise unassigned.
구조체의 인스턴스 변수는 그것이 속한 구조체 변수와 정확히 동일한 수명을 가집니다. 즉, 구조체 유형의 변수가 존재하거나 존재하지 않으면 구조체의 인스턴스 변수도 마찬가지입니다. 구조체 인스턴스 변수의 초기 할당 상태는 포함하는 구조체 변수의 초기 할당 상태와 동일합니다. 즉, 구조체 변수가 초기에 할당된 것으로 간주되면 인스턴스 변수도 마찬가지이며 구조체 변수가 초기에 할당되지 않은 것으로 간주되면 해당 인스턴스 변수도 마찬가지로 할당되지 않은 것입니다.
Array elements
Value parameters
Reference parameters
다른 글 작성해서 링크 추가예정
Output parameters
다른 글 작성해서 링크 추가예정
Definite assignment (명확한, 확실한 할당)
변수가 함수 member의 실행 가능한 코드 또는 anonymous function에 위치에서 컴파일러가 정적 흐름 분석(static flow analysis)을 통해 자동으로 할당되었음을 증명할 수 있는 경우를 변수가 definitely하게 할당되었다고 얘기합니다. 또는 변수가 자동으로 초기화되거나 적어도 하나의 할당 대상인 경우에도 definitely하게 할당되었다고 얘기합니다.
특징 요약
- 초기화되지 않은 변수들을 사용하지 못하게 합니다. (컴파일러에 의해 정적으로 확인)
- C#은 명확한 할당을 필수로 하며, 이 말은 변수가 사용되기 전에 초기화(할당) 되어야 한다는 뜻입니다.
http://www.csharpstudy.com/CSharp/CSharp-variable.aspx
https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/language-specification/variables
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/variables
https://artiper.tistory.com/124
https://www.javatpoint.com/net-framework-class-library
https://www.csharpstudy.com/CSharp/CSharp-anonymous-type.aspx
'C#' 카테고리의 다른 글
[C#] CS0273에러 accessor must be more restrictive than the property or indexer (1) | 2024.09.25 |
---|---|
[C#] 데이터 타입 (0) | 2023.01.05 |
[C#] Boxing과 Unboxing에 대하여 (0) | 2021.08.08 |
[Unity, C#] 중첩 클래스(Nested Class) (0) | 2021.05.02 |
[C#] 배열의 default 초기화 (0) | 2021.04.30 |