C# [ 패턴 매칭 ]

손정훈·2023년 9월 19일

패턴매칭

어떤 식이 특정 패턴과 일치하는지를 검사


선언패턴

  1. 식이 주어진 형식과 일치하는지 테스트
  2. 테스트가 성공하면 식을 주어진 형식으로 변환
object foo = 23;
//  1. foo가 int인 경우 2. foo를 int 형식으로 변환하며 bar에 할당
if (foo is int bar)
{
	console.WriteLine(bar);
}

형식 패턴

변수 생성 없이 형식 일치 여부만 테스트

object foo = 23;
if(foo is int)
{
	Console.WriteLine(foo);
}

상수 패턴

식이 특정 상수와 일치하는지를 검사

var GetCountryCode = (string nation) => nation switch
{
	"KR" => 82,
    "US" => 1,
    "UK" => 44,
    _ => throw new ArgumentException("Not supported Code")
};
Console.WriteLine(GetCountryCode("KR"));	// 82
Console.WriteLine(GetCountryCode("US"));	// 1
Console.WriteLine(GetCountryCode("UK"));	// 44

프로퍼티 패턴

식이 속성이나 필드가 패턴과 일치하는지 검사

class Car
{
	public string Model {get; set;}
    public DateTime ProducedAt {get; set;}
}

static string GetNickname(Car car)
{
	var GemerateMessage = (Car car, string nickname) =>
    	$"{car.Model} produced in {car.ProducedAt.Year} in {nickname}";
    if(car is Car {Model:"Mustang", ProductedAt.Year: 1967})
    	return GenerateMessage(car, "Fastback")l
    else
    	return GenerateMessage(car, "Unknown");
}

static void Main(string[] args)
{
	Console.WriteLine(
    	GetNuckname(
        	new Car() {Model = "Mustang", ProducedAt = new DateTime(1967, 11, 23)}));
}

관계 패턴

>, >=, ==, != 등 관계연산자를 이용하여 입력받은 식을 상수와 비교

static int IsPassed(double score) => score switch
{
	< 60 => false	// score가 60보다 작으면 false
    _	 => true,	// 60보다 크면 true
}

논리 패턴

패턴과 패턴을 패턴 논리 연산자로 조합해서 하나의 논리패턴으로 만듦


괄호 패턴

소괄호 ()로 패턴을 감쌈

object age = 30;

if(age is (int and > 19))
	Console.WriteLine("Major");

위치 패턴

식의 결과를 분해하고, 분해된 값들이 내장된 복수의 패턴과 일치하는지 검사

Tuple<string, int> itemPrice = new Tuple<string, int>("espresso", 3000);
if(itemPrice is ("espresso", < 5000))	// espresso이고 5000보다 작은지 검사
{
	Console.WriteLine("The coffee is affordable.");
}

Var 패턴

null을 포함한 모든 식의 패턴 매칭을 성공시키고, 그 식의 결과를 변수에 할당

// 모든 과목이 60점이 넘고, 평균이 60점 이상인 경우 Pass
var IsPassed = 
	(int[] scores) => scores.Sum() / scores.Length is var average
	&& Array.TrueForAll(scores, (score) => score >= 60)
    && average >= 60;

무시 패턴

var 패턴처럼 모든 식과의 패턴 일치 검사하며, is식 사용 불가, switch 식에서만 사용 가능

var GetCountryCode = (string nation) => nation switch
{
	"KR" => 82,
    "US" => 1,
    "UK" => 44,
    _ => throw new ArgumentException("Not supported Code")
};

// KR, US, UK에 모두 일치하지 않기떄문에 _에 매칭
Console.WriteLine(GetCountryCode("JP"));	// Not supported Code 출력

목록 패턴

배열이나 리스트가 패턴의 스퀀스와 일치하는지 검사

var match = (int[] array) => array is [int, >10, _];
Console.WriteLine(match(new int[] {1, 100, 3}));	// True
Console.WriteLine(match(new int[] {100, 10, 999}));	// false
// 두번째 요소 10이 패턴 시퀀스의 요소 >10과 일치하지 않음

0개의 댓글