연습 - 데이터 형식 캐스팅 및 변환 살펴보기
- 30분
데이터 형식 변환을 수행하기 위한 여러 기술이 있습니다. 어느 기술을 선택할 것인지는 다음과 같은 두 개의 중요한 질문에 대한 답변에 따라 달라집니다.
- 값의 데이터 형식을 변경하려고 시도하면 런타임에 예외가 throw될 가능성이 있나요?
- 값의 데이터 형식을 변경하려고 시도하면 정보가 손실될 가능성이 있나요?
이 연습에서는 이러한 질문과 답변의 의미를 처음부터 끝까지 살펴보고 데이터 형식을 변경해야 할 때 어느 기술을 사용할 것인지 살펴봅니다.
코딩 환경 준비
이 모듈에는 데모 코드를 빌드하고 실행하는 프로세스를 안내하는 실습 활동이 포함되어 있습니다. Visual Studio Code를 개발 환경으로 사용하여 이러한 활동을 완료하는 것이 좋습니다. 이러한 활동에 Visual Studio Code를 사용하면 전 세계 전문가가 사용하는 개발자 환경에서 코드를 더 편안하게 작성하고 실행할 수 있습니다.
참고
이 C# 시리즈에서 다른 Microsoft Learn 모듈을 완료한 경우 코드 샘플용 프로젝트 폴더를 이미 만들었을 수 있습니다. 이 경우 다음 단계 섹션을 건너뛰고 이전 연습에 사용된 Program.cs
파일에서 코드를 삭제할 수 있습니다.
참고
이 연습의 코드 샘플은 en-US 문화권 설정을 기반으로 설계되었으며 마침표(.
)를 소수 구분 기호로 사용합니다. 다른 소수 구분 기호(예: 쉼표 ,
)를 사용하는 문화권 설정으로 코드를 빌드하고 실행하면 예기치 않은 결과나 오류가 발생할 수 있습니다. 이 문제를 해결하려면 코드 샘플의 마침표 소수 구분 기호를 로컬 소수 구분 기호(예: ,
)로 바꿉니다.
또한 "en-US" 문화권 설정을 사용하여 프로그램을 실행하려면 using System.Globalization;
프로그램 맨 위에 다음 코드를 추가하고 그 외 기타 using
문 뒤에 CultureInfo.CurrentCulture = new CultureInfo("en-US");
를 추가합니다.
Visual Studio Code를 엽니다.
Windows 시작 메뉴(또는 다른 OS의 해당 리소스)를 사용하여 Visual Studio Code를 열 수 있습니다.
Visual Studio Code 파일 메뉴에서 폴더 열기를 선택합니다.
폴더 열기 대화 상자에서 Windows 데스크톱 폴더로 이동합니다.
코드 프로젝트를 유지하는 다른 폴더 위치가 있는 경우 해당 폴더 위치를 대신 사용할 수 있습니다. 이 학습에서는 쉽게 기억하고 찾을 수 있는 위치를 사용하는 것이 중요합니다.
폴더 열기 대화 상자에서 폴더 선택을 선택합니다.
작성자를 신뢰할 수 있는지 묻는 보안 대화 상자가 표시되면 예를 선택합니다.
Visual Studio Code 터미널 메뉴에서 새 터미널을 선택합니다.
터미널 패널의 명령 프롬프트에 현재 폴더의 폴더 경로가 표시됩니다. 예를 들면 다음과 같습니다.
C:\Users\someuser\Desktop>
지정된 폴더에 새 콘솔 애플리케이션을 만들려면 터미널 명령 프롬프트에서
dotnet new console -o ./CsharpProjects/TestProject
를 입력한 다음, Enter 키를 누릅니다.이 .NET CLI 명령은 .NET 프로그램 템플릿을 사용하여 지정된 폴더 위치에 새 C# 콘솔 애플리케이션 프로젝트를 만듭니다. 이 명령은 CsharpProjects 및 TestProject 폴더를 만들고 TestProject를
.csproj
파일의 이름으로 사용합니다.탐색기 패널에서 CsharpProjects 폴더를 확장합니다 .
TestProject 폴더와 두 개의 파일, 즉 Program.cs라는 C# 프로그램 파일과 TestProject.csproj라는 C# 프로젝트 파일이 표시됩니다.
탐색기 패널의 편집기 패널에서 코드 파일을 보려면 Program.cs 선택합니다.
기존 코드 줄을 삭제합니다.
이 모듈을 진행하는 동안 이 C# 콘솔 프로젝트를 사용하여 코드 샘플을 만들고, 빌드하고, 실행합니다.
터미널 패널을 닫습니다.
질문: 값의 데이터 형식을 변경하려고 시도하면 런타임에 예외가 throw될 가능성이 있나요?
C# 컴파일러는 코드를 수용하려고 시도하지만, 예외를 발생시킬 수 있는 작업을 컴파일하지 않습니다. C# 컴파일러의 기본 고려 사항을 이해하면 특정 방식으로 작동하는 이유를 이해하는 것이 보다 쉬워집니다.
int
와 string
을 추가하고 결과를 int
에 저장하려고 시도하는 코드 작성
Visual Studio Code가 열려 있고 편집기 패널에 Program.cs가 표시되는지 확인합니다.
참고
Program.cs는 비어 있어야 합니다. 그렇지 않은 경우 모든 코드 줄을 선택하고 삭제합니다.
Visual Studio Code 편집기에 다음 코드를 입력합니다.
int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);
여기서는 값
2
및4
를 더하려고 시도합니다. 값4
는string
형식입니다. 덧셈이 가능할까요?Visual Studio Code 파일 메뉴에서 저장을 선택합니다.
코드를 빌드하거나 실행하기 전에 Program.cs 파일을 저장해야 합니다.
탐색기 패널에서 TestProject 폴더 위치에서 터미널을 열려면 TestProject를 마우스 오른쪽 단추로 클릭한 다음 통합 터미널에서 열기를 선택합니다.
터미널 패널이 열려 있어야 하고 터미널이 TestProject 폴더 위치에 열려 있음을 보여 주는 명령 프롬프트를 포함해야 합니다.
터미널 명령 프롬프트에서 코드를 실행하려면
dotnet run
을 입력한 다음, Enter 키를 누릅니다.다음과 같은 대략적인 출력이 표시됩니다.
C:\Users\someuser\Desktop\csharpprojects\TestProject\Program.cs(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int'
참고
“실행할 프로젝트를 찾을 수 없습니다.”라는 메시지가 표시되면 터미널 명령 프롬프트에 예상되는 TestProject 폴더 위치가 표시되는지 확인합니다. 예:
C:\Users\someuser\Desktop\csharpprojects\TestProject>
잠시 시간을 내어 컴파일러가 첫 번째 코드 샘플을 실행할 수 없었던 이유를 생각해 봅니다.
오류 메시지의 중요한 부분인
(3,14): error CS0029: Cannot implicitly convert type 'string' to 'int'
는string
데이터 형식 사용에 문제가 있다는 것을 알려 줍니다.그런데 C# 컴파일러는 왜 이 오류를 처리하지 못할까요? 반대로, 숫자를 에 연결하여 문자열 변수에 저장하는 것은 가능한데 말입니다. 여기서
result
변수의 데이터 형식을int
에서string
으로 변경합니다.다음과 같이 Visual Studio Code 편집기에서 코드를 업데이트합니다.
int first = 2; string second = "4"; string result = first + second; Console.WriteLine(result);
코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다.
다음과 같이 출력됩니다.
24
출력은 수학적으로 올바르지 않지만 값을 문자 “2”와 “4”로 결합하여 완료됩니다.
result
변수가int
형식인 첫 번째 코드 예제를 다시 한 번 살펴봅니다. 오류 메시지가 있는 코드.int first = 2; string second = "4"; int result = first + second; Console.WriteLine(result);
C# 컴파일러는 왜
second
가 포함된 변수4
를string
이 아닌 숫자로 처리하고자 한다는 것을 알아내지 못하는 걸까요?
컴파일러가 안전한 변환 수행
C# 컴파일러는 여기에서 잠재적인 문제를 발견합니다. 변수 second
는 string
형식이므로 "hello"
같은 다른 값으로 설정될 수도 있습니다. C# 컴파일러가 "hello"
를 숫자로 변환하려고 시도한다면 이로 인해 런타임에 예외가 발생할 것입니다. 이러한 가능성을 방지하기 위해 C# 컴파일러는 자동으로 string
에서 int
로 변환을 암시적으로 수행하지 않습니다.
C# 컴파일러의 관점에서 보면 int
를 string
으로 변환하고 연결을 수행하는 것이 더 안전한 연산일 것입니다.
문자열을 사용한 덧셈을 수행하려는 경우 C# 컴파일러는 데이터 변환 프로세스를 보다 명시적으로 제어할 것을 요구합니다. 즉, 변환이 예외를 throw시킬 가능성을 처리하기 위한 올바른 주의를 기울일 수 있도록 사용자가 적극적으로 개입하는 것을 강제합니다.
값을 원래 데이터 형식에서 새 데이터 형식으로 변경해야 하고 변경으로 인해 런타임에 예외가 발생할 수 있는 경우 데이터 변환을 수행해야 합니다.
데이터 변환을 수행하려면 다음 기법 중 하나를 사용하면 됩니다.
- 데이터 형식에 도우미 메서드를 사용합니다.
- 변수에 대해 도우미 메서드를 사용합니다.
-
Convert
클래스의 메서드 사용
이 단원의 뒷부분에서 데이터 변환을 위한 해당 기술의 몇 가지 예제를 살펴봅니다.
질문: 값의 데이터 형식을 변경하려고 시도하면 정보가 손실될 가능성이 있나요?
줄 주석 연산자
//
를 삭제하거나 사용하여 이전 연습 단계의 코드를 주석으로 처리하고 다음 코드를 추가합니다.int myInt = 3; Console.WriteLine($"int: {myInt}"); decimal myDecimal = myInt; Console.WriteLine($"decimal: {myDecimal}");
코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다.
다음 출력이 표시됩니다.
int: 3 decimal: 3
이 예제의 핵심은 다음 코드 줄입니다.
decimal myDecimal = myInt;
int
값은decimal
안에 문제없이 들어갈 수 있으므로 컴파일러가 변환을 수행합니다.확대 변환이라는 용어는 더 적은 정보를 보유할 수 있는 데이터 형식에서더 많은 정보를 보유할 수 있는 데이터 형식으로 값을 변환하려고 한다는 것을 의미합니다. 이 경우
int
형식의 변수로 변환된decimal
형식의 변수에 저장된 값은 정보가 손실되지 않습니다.확대 변환을 수행하고 있다는 것을 알고 있는 경우 암시적 변환에 의존할 수 있습니다. 컴파일러는 암시적 변환을 처리합니다.
캐스트 수행
줄 주석 연산자
//
를 삭제하거나 사용하여 이전 연습 단계의 코드를 주석으로 처리하고 다음 코드를 추가합니다.decimal myDecimal = 3.14m; Console.WriteLine($"decimal: {myDecimal}"); int myInt = (int)myDecimal; Console.WriteLine($"int: {myInt}");
캐스트를 수행하려면 캐스팅 연산자
()
를 사용하여 데이터 형식을 묶은 다음, 변환하려는 변수 옆에 배치합니다(예:(int)myDecimal
). 정의된 캐스트 데이터 형식(int
)으로 명시적 변환을 수행합니다.코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다.
다음 출력이 표시됩니다.
decimal: 3.14 int: 3
이 예제의 핵심은 다음 코드 줄입니다.
int myInt = (int)myDecimal;
myDecimal
변수는 소수점 뒤에 소수 자릿수가 있는 값을 포함합니다. 캐스팅 명령(int)
를 추가하여 C# 컴파일러에 소수 자릿수가 손실될 수 있음을 알고 있지만 이를 허용하겠다고 알려 줍니다. 의도적인 변환, 명시적 변환을 수행하고 있음을 컴파일러에 알리는 것입니다.
변환이 “확대 변환”인지 “축소 변환”인지 확인
축소 변환이라는 용어는 더 많은 정보를 보유할 수 있는 데이터 형식에서 더 적은 정보를 보유할 수 있는 데이터 형식으로 값을 변환하려고 한다는 것을 의미합니다. 이 경우 정밀도(소수점 이하 값의 개수)와 같은 정보를 잃게 됩니다. 예를 들어 decimal
형식의 변수에 저장된 값을 int
형식의 변수로 변환하는 것입니다. 두 값을 출력하면 정보가 손실된 것을 알 수 있습니다.
축소 변환을 수행하고 있다는 것을 알고 있는 경우 캐스트를 수행해야 합니다. 캐스팅이란 정밀도가 손실될 수도 있음을 알고 있지만 이를 허용하겠다고 C# 컴파일러에 알리는 것입니다.
변환에서 데이터가 손실되는지 확실하지 않은 경우 두 가지 방법으로 변환을 수행하는 코드를 작성하고 변경 내용을 관찰합니다. 개발자는 다음 샘플과 같이 동작을 더 잘 이해하기 위해 작은 테스트를 자주 작성합니다.
줄 주석 연산자
//
를 삭제하거나 사용하여 이전 연습 단계의 코드를 주석으로 처리하고 다음 코드를 추가합니다.decimal myDecimal = 1.23456789m; float myFloat = (float)myDecimal; Console.WriteLine($"Decimal: {myDecimal}"); Console.WriteLine($"Float : {myFloat}");
코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다.
다음과 유사한 결과가 표시됩니다.
Decimal: 1.23456789 Float : 1.2345679
decimal
을float
로 캐스팅하는 것은 소수 자릿수가 손실되기 때문에 축소 변환임을 출력에서 알 수 있습니다.
데이터 변환 수행
이전에는 한 데이터 형식에서 다른 데이터 형식으로 값을 변경하면 런타임 예외가 발생할 수 있으며 데이터 변환을 수행해야 한다고 설명했습니다. 데이터 변환의 경우 다음 세 가지 기술을 사용할 수 있습니다.
- 변수에 대해 도우미 메서드를 사용합니다.
- 데이터 형식에 도우미 메서드를 사용합니다.
-
Convert
클래스의 메서드 사용
ToString()
을 사용하여 숫자를 string
으로 변환
모든 데이터 형식 변수에는 ToString()
메서드가 있습니다.
ToString()
메서드가 무엇을 하는지는 해당 유형에서 이 메서드가 구현된 방식에 따라 달라집니다. 그렇긴 하나, 대부분의 기본 형식에서 이 메서드는 확대 변환을 수행합니다. 대부분의 경우 명시적 변환을 사용해도 되므로 이 단계가 꼭 필요한 것은 아니지만, 이 단계를 수행하면 원래 개발자가 변환의 영향을 잘 알고 있고 이 변환이 의도적이라는 것을 다른 개발자들에게 전달할 수 있습니다.
다음은 ToString()
메서드를 사용하여 int
값을 string
으로 명시적으로 변환하는 간단한 예입니다.
줄 주석 연산자
//
를 삭제하거나 사용하여 이전 연습 단계의 코드를 주석으로 처리하고 다음 코드를 추가합니다.int first = 5; int second = 7; string message = first.ToString() + second.ToString(); Console.WriteLine(message);
코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다. 코드를 실행하면 출력에 두 값의 연결이 표시됩니다.
57
string
도우미 메서드를 사용하여 int
을 Parse()
로 변환
대부분의 숫자 데이터 형식에는 Parse()
메서드가 있습니다. 이 메서드는 문자열을 지정된 데이터 형식으로 변환합니다. 이 경우 Parse()
메서드를 사용하여 두 개의 문자열을 int
값으로 변환한 다음, 두 값을 더합니다.
줄 주석 연산자
//
를 삭제하거나 사용하여 이전 연습 단계의 코드를 주석으로 처리하고 다음 코드를 추가합니다.string first = "5"; string second = "7"; int sum = int.Parse(first) + int.Parse(second); Console.WriteLine(sum);
코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다. 코드를 실행하면 출력에 두 값의 합이 표시됩니다.
12
잠시 시간을 내어 이전 코드 예제의 잠재적인 문제를 파악해 볼까요? 변수
first
와second
중 하나가int
로 변환될 수 없는 값으로 설정되었다면 어떨까요? 런타임에 예외가 throw됩니다. C# 컴파일러 및 런타임에서는 “불법적” 변환을 미리 계획하고 방지해야 합니다. 여러 가지 방법으로 런타임 예외를 완화할 수 있습니다.가장 쉬운 방법은
TryParse()
메서드의 향상된 버전인Parse()
를 사용하는 것입니다.
string
클래스를 사용하여 int
을 Convert
로 변환
Convert
클래스에는 값을 하나의 형식에서 다른 형식으로 변환하는 여러 도우미 메서드가 있습니다. 다음 코드 예제에서 문자열 두 개를 int
형식의 값으로 변환합니다.
줄 주석 연산자
//
를 삭제하거나 사용하여 이전 연습 단계의 코드를 주석으로 처리하고 다음 코드를 추가합니다.string value1 = "5"; string value2 = "7"; int result = Convert.ToInt32(value1) * Convert.ToInt32(value2); Console.WriteLine(result);
코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다.
다음 출력이 표시됩니다.
35
참고
메서드 이름이 왜
ToInt32()
일까요? 왜ToInt()
가 아닐까요?System.Int32
는 C# 프로그래밍 언어가 키워드int
에 매핑하는 .NET 클래스 라이브러리의 기본 데이터 형식입니다.Convert
클래스도 .NET 클래스 라이브러리의 일부이므로 C# 이름이 아닌 전체 이름으로 호출됩니다. 데이터 형식을 .NET 클래스 라이브러리의 일부로 정의하면 Visual Basic, F#, IronPython 등과 같은 여러 .NET 언어들이 .NET 클래스 라이브러리의 동일한 데이터 형식과 동일한 클래스를 공유할 수 있습니다.ToInt32()
메서드에는 19개의 오버로드된 버전이 있기 때문에 거의 모든 데이터 형식을 수락할 수 있습니다.여기서는 문자열에
Convert.ToInt32()
메서드를 사용했지만, 가능한 경우TryParse()
를 사용할 수 있어야 합니다.그렇다면
Convert
클래스는 언제 사용해야 할까요?Convert
클래스는 숫자를 사용자의 예상대로 반올림하므로 분수를 정수(int
)로 변환할 때 가장 좋습니다.
decimal
을 int
로 캐스팅 및 변환 비교
다음 예제에서는 decimal
을 int
로 캐스팅하려고 시도할 때(축소 변환)와 Convert.ToInt32()
메서드를 사용하여 동일한 decimal
을 int
로 변환할 때 무슨 일이 일어나는지를 비교하여 보여 줍니다.
줄 주석 연산자
//
를 삭제하거나 사용하여 이전 연습 단계의 코드를 주석으로 처리하고 다음 코드를 추가합니다.int value = (int)1.5m; // casting truncates Console.WriteLine(value); int value2 = Convert.ToInt32(1.5m); // converting rounds up Console.WriteLine(value2);
코드 파일을 저장한 다음, Visual Studio Code를 사용하여 코드를 실행합니다.
다음 출력이 표시됩니다.
1 2
캐스팅 잘림 및 변환 반올림/반내림
int value = (int)1.5m;
을 캐스팅하는 경우 float의 값이 잘리므로 결과는 소수점 뒤의 값이 완전히 무시됨을 의미하는 1
입니다. 리터럴 float를 1.999m
으로 변경할 수 있으며 캐스팅 결과는 동일합니다.
Convert.ToInt32()
를 사용하여 변환하면 리터럴 float 값이 2
로 제대로 반올림됩니다. 리터럴 값을 1.499m
으로 변경하면 1
로 반내림됩니다.
요약
데이터 변환 및 캐스팅에 관한 여러 가지 중요한 개념을 살펴보았습니다.
- 데이터 변환을 수행하는 동안 런타임 오류 방지
- 데이터 손실 위험을 이해하고 있음을 컴파일에 알려 주는 명시적 캐스트 수행
- 확대 변환을 수행할 때 컴파일러를 사용하여 암시적 캐스트 수행
-
()
캐스트 연산자와 데이터 형식을 사용하여 캐스트 수행(예:(int)myDecimal
) - 축소 변환을 수행하고자 하지만 정보가 잘리지 않고 반올림/반내림되도록 하려는 경우
Convert
클래스 사용