
"이 메서드 안에서만 잠깐 쓸 건데... 굳이 새 클래스 파일을 만들어야 하나?"
C#은 이럴 때 실용적이고 편리한 무명 형식(Anonymous Type)을 제공하고 있습니다.
무명 형식은 마치 정보를 급하게 메모해야 할 때, '포스트잇'에 쓰는 것과 같아요.
무명 형식(Anonymous Type)은 new { ... }구문을
사용하여 이름 없는 객체를 즉석에서 만드는 기능입니다.
컴파일러는 우리가 할당한 속성을 보고 내부적으로 이름과 형식을
가진 클래스를 만들어 줍니다. 우리는 그 이름을 알 필요가 없을 뿐이죠.
사용법은 간단합니다. var키워드와 new초기화 구문을 함께 사용하면 됩니다.
var: 컴파일러가 생성한 형식을 모르기 때문에 var를 사용해야만 합니다.
new { ... }: 구문 안에 속성이름 = 값 형태로 원하는 데이터를 넣어줍니다.
[코드]
// 'Name'과 'Price'라는 속성을 가진 무명 형식 객체 생성
var product = new { Name = "노트북", Price = 1500000 };
// 속성에 접근하는 방법은 일반 객체와 동일
Console.WriteLine($"제품명: {product.Name}");
Console.WriteLine($"가격: {product.Price}원");
[실행 결과]
제품명: 노트북
가격: 1500000원
무명 형식은 몇 가지 중요한 특징을 가지고 있습니다.
무명 형식의 가장 중요한 특징 중 하나는 불변성(Immutable)입니다.
한번 생성되면 그 속성의 값을 절대 바꿀 수 없습니다.
[코드]
var car = new { Brand = "Hyundai", Year = 2025 };
Console.WriteLine($"{car.Brand}, {car.Year}");
// car.Brand = "Kia"; // 읽기 전용 속성이므로 컴파일 오류!
[실행 결과]
Hyundai, 2025
컴파일러는 무명 형식을 위해 몇 가지 유용한 메서드를 재정의(override)해 줍니다.
ToString(): 객체의 속성과 값을 보기 좋은 문자열로 만들어 줍니다.
Equals() & GetHashCode(): 값 기반으로 동등성을 비교합니다.
[코드]
var product1 = new { Name = "키보드", Price = 120000 };
var product2 = new { Name = "키보드", Price = 120000 };
Console.WriteLine(product1.ToString());
Console.WriteLine($"product1 == product2 : {product1.Equals(product2)}");
[실행 결과]
{ Name = 키보드, Price = 120000 }
product1 == product2 : True
무명 형식에서는 변수 이름을 그대로 속성 이름으로 사용할 수도 있습니다.
이 기능을 '암시적 속성명(Implicit Property Name)'이라고 부릅니다.
[코드]
string studentName = "홍길동";
int studentAge = 21;
// 암시적 속성명(Implicit Property Name)
// 변수 이름만 적어주면, C# 컴파일러가 알아서
// 변수 이름(studentName, studentAge)을 그대로 속성 이름으로 사용해요.
var student2 = new { studentName, studentAge };
Console.WriteLine($"이름: {student2.studentName}, 나이: {student2.studentAge}");
[실행 결과]
이름: 홍길동, 나이: 21
무명 형식은 다른 무명 형식 안에 중첩 선언도 가능합니다.
[코드]
var student = new
{
Name = "김철수",
Grade = 3,
Address = new { City = "서울", ZipCode = "12345" }
};
Console.WriteLine($"이름: {student.Name}, 주소: {student.Address.City}");
[실행 결과]
이름: 김철수, 주소: 서울
이름이 없다고 해서 형식까지 없는 것은 아닙니다. 무명 형식은 컴파일 시점에
모든 속성의 타입이 결정되는 강력한 형식(Strongly Typed)입니다.
덕분에 우리는 비주얼 스튜디오에서 자동 완성 기능(IntelliSense)의
도움을 받을 수 있고, 컴파일 시점에 타입 오류를 잡아낼 수 있습니다.
무명 형식은 편리하지만 주로 하나의 메서드 안에서 임시로 사용됩니다.
메서드의 반환 값이나 다른 메서드의 매개변수로 전달하기에는 까다롭습니다.
(물론 object, dynamic으로 형변환하면 가능하지만, 타입 안정성을 잃어버립니다.)
이럴 때는 튜플(Tuple)이라는 훌륭한 대안이 있습니다.
무명 형식은 LINQ(Language-Integrated Query)와 함께 사용할 때
엄청난 시너지를 발휘합니다. 데이터 목록에서 내가 원하는
특정 정보들만 뽑아서 새로운 임시 목록을 만들 때 아주 유용합니다.
쇼핑몰에 Product클래스가 있고, 상품 목록이 있다고 가정해 봅시다.
여기서 우리는 각 상품의 '이름'과 '세금이 포함된 가격'만 뽑아서 보고 싶습니다.
[코드]
using System;
using System.Collections.Generic; // List<T>를 사용하기 위해 필수!
using System.Linq; // LINQ를 사용하기 위해 필수!
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
class Program
{
static void Main()
{
// 1. 원본 상품 데이터 리스트
List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "노트북", Price = 1200000 },
new Product { Id = 2, Name = "마우스", Price = 50000 },
new Product { Id = 3, Name = "키보드", Price = 85000 }
};
// 2. LINQ의 Select 메서드와 무명 형식을 사용하여 원하는 데이터만 추출
var saleProducts = products.Select(p => new
{
ProductName = p.Name,
PriceWithTax = p.Price * 1.1
});
// 3. 결과 출력
Console.WriteLine("--- 판매용 상품 정보 ---");
foreach (var item in saleProducts)
{
Console.WriteLine($"{item.ProductName}: {item.PriceWithTax:N0}원");
// item의 실제 타입 이름은 무엇일까요?
// 궁금하다면 아래 코드의 주석을 해제하고 실행해보세요.
// Console.WriteLine($"(실제 타입: {item.GetType().Name})");
}
}
}
[실행 결과]
--- 판매용 상품 정보 ---
노트북: 1,320,000원
마우스: 55,000원
키보드: 93,500원
무명 형식 덕분에 즉석에서 원하는 데이터 구조를 만들어 사용할 수 있었습니다.
무명 형식은 '포스트잇'처럼, 특정 작업을 빠르고 간편하게
처리하고 싶을 때 사용하는 C#의 작지만 강력한 도구입니다.
| 구분 | 클래스(Class) | 무명 형식(Anonymous Type) |
|---|---|---|
| 이름 | 있음 | 없음 |
| 정의 | class MyClass { ... } | new { Prop = value } |
| 용도 | 재사용 가능한 데이터 구조 정의 | 메서드 내에서 임시 데이터 묶음, LINQ 쿼리 결과 |