IFormattable은 객체를 특정 형식(format)으로 변환할 수 있도록 하는 인터페이스다.
즉,
ToString(string format, IFormatProvider formatProvider)메서드를 구현해야 한다.
ToString() 메서드에 형식을 지정하여 다양한 포맷으로 변환할 수 있다.int, double, DateTime 등 기본 타입들도 IFormattable을 구현하고 있다.where T : IFormattable을 사용하여 특정 타입만 받도록 제한을 주는 것이 가능하다.IFormattable을 구현하면, 형식 변환 기능을 커스터마이징할 수 있다.또한, IFormattable인터페이스의 필수 구현 메서드는 다음과 같다.
public interface IFormattable
{
string ToString(string format, IFormatProvider formatProvider);
}
// 이 메서드만 구현하면 IFormattable을 지원하는 클래스가 된다.
int, double, DateTime)의 IFormattable활용 예제int number = 12345;
Console.WriteLine(number.ToString("N0")); // 12,345
double price = 123.456;
Console.WriteLine(price.ToString("F2")); // 123.46
DateTime now = DateTime.Now;
Console.WriteLine(now.ToString("yyyy-MM-dd")); // 2025-03-17 (예제 날짜)
int, double, DateTime 등은 이미 IFormattable을 구현하고 있어서 다양한 형식으로 출력이 가능하다.위 예제에서 ToString("N0"), ToString("F2"), ToString("yyyy-MM-dd")을 호출할 때 IFormatProvider를 명시적으로 전달하지 않았는데도 잘 동작하는 이유는 기본적으로 .NET이 CultureInfo.CurrentCulture를 사용하기 때문이다.
System.Globalization.CultureInfo.CurrentCulture
CultureInfo.CurrentCulture는 현재 실행 중인 스레드의 문화권 정보를 나타낸다.- OS 설정에 따라 결정되며, 예를 들어 한국어 환경에서는 "ko-KR"이 기본값이다.
기본 ToString() 동작 흐름
public string ToString(string format)
{
return ToString(format, CultureInfo.CurrentCulture);
}
즉, 우리가 ToString("N0")처럼 IFormatProvider 없이 호출하면, 내부적으로 자동으로 CultureInfo.CurrentCulture를 사용하게 된다.
아래 코드로 현재 문화권을 확인해 볼 수도 있다.
using System;
using System.Globalization;
class Program
{
static void Main()
{
Console.WriteLine(CultureInfo.CurrentCulture.Name); // 현재 문화권 출력 (예: "ko-KR" or "en-US")
}
}
IFormattable구현하기사용자 정의 클래스 예제
using System;
public class Product : IFormattable
{
public string Name { get; set; }
public decimal Price { get; set; }
// IFormattable 메서드 구현
public string ToString(string format, IFormatProvider formatProvider)
{
if (string.IsNullOrEmpty(format)) format = "G"; // 기본 형식 General
switch (format.ToUpper())
{
case "G": return $"{Name} - {Price:C}"; // 기본 형식 (통화 표기)
case "N": return $"{Name} (Price: {Price:N2})"; // 숫자 형식 (소수점 2자리)
case "P": return $"[{Name}] ${Price}"; // 간단한 출력
default: throw new FormatException($"Invalid format '{format}'");
}
}
public override string ToString() => ToString("G", null);
}
// 사용 예제
Product product = new Product { Name = "Laptop", Price = 1200.50m };
Console.WriteLine(product.ToString("G", null)); // Laptop - $1,200.50
Console.WriteLine(product.ToString("N", null)); // Laptop (Price: 1,200.50)
Console.WriteLine(product.ToString("P", null)); // [Laptop] $1200.50
// 기본 ToString() 호출
Console.WriteLine(product); // Laptop - $1,200.50
IFormattable을 직접 구현하면, 사용자 정의 형식으로 객체를 문자열로 변환 가능하다!IFormattable을 제네릭 제약 조건으로 사용public class Formatter<T> where T : IFormattable
{
public void PrintFormatted(T value, string format)
{
Console.WriteLine(value.ToString(format, null));
}
}
// 사용 예제
Formatter<int> intFormatter = new Formatter<int>();
intFormatter.PrintFormatted(12345, "N0"); // 12,345
Formatter<double> doubleFormatter = new Formatter<double>();
doubleFormatter.PrintFormatted(123.456, "F2"); // 123.46
Formatter<DateTime> dateFormatter = new Formatter<DateTime>();
dateFormatter.PrintFormatted(DateTime.Now, "yyyy-MM-dd"); // 2025-03-17
where T : IFormattable을 사용하면, 형식 변환이 가능한 타입만 받을 수 있도록 제한할 수 있다.| 개념 | 설명 |
|---|---|
| IFormattable 인터페이스 | 형식 변환이 가능하도록 ToString(string format, IFormatProvider provider)을 요구 |
| 기본 구현 타입 | int, double, DateTime 등은 이미 IFormattable을 구현 |
| 사용자 정의 클래스 구현 가능 | IFormattable을 직접 구현하여 원하는 형식으로 문자열 변환 가능 |
| 제네릭 제약 조건 | where T : IFormattable을 사용하여 특정 타입만 받도록 제한 가능 |
| 컬렉션과 함께 사용 | where T : IEnumerable<IFormattable>을 사용하여 IFormattable을 구현한 요소들만 포함하는 컬렉션을 제한 가능 |
IFormattable을 사용하면 객체를 특정 형식으로 변환하는 기능을 쉽게 추가할 수 있다.int, double, DateTime) 외에도 사용자 정의 클래스에서 직접 구현 가능하다.