기능 언어 (예 : lisp)에서는 패턴 일치를 사용하여 목록의 특정 요소에 어떤 일이 발생하는지 확인합니다. C #에서 동등한 것은 요소의 유형을 확인하고이를 기반으로 작업을 수행하는 if ... elseif 문의 체인입니다. 말할 필요도없이, 기능 패턴 일치는 런타임 유형 검사보다 효율적입니다.
다형성을 사용하는 것이 패턴 일치에 더 가깝습니다. 즉, 목록의 객체가 특정 인터페이스와 일치하도록하고 각 객체에 대해 해당 인터페이스에서 함수를 호출합니다. 또 다른 대안은 특정 객체 유형을 매개 변수로 취하는 일련의 오버로드 된 메소드를 제공하는 것입니다. Object를 매개 변수로 사용하는 기본 방법입니다.
public class ListVisitor
{
public void DoSomething(IEnumerable<dynamic> list)
{
foreach(dynamic obj in list)
{
DoSomething(obj);
}
}
public void DoSomething(SomeClass obj)
{
//do something with SomeClass
}
public void DoSomething(AnotherClass obj)
{
//do something with AnotherClass
}
public void DoSomething(Object obj)
{
//do something with everything els
}
}
이 접근 방식은 Lisp 패턴 일치에 대한 근사치를 제공합니다. 방문자 패턴 (여기에서 구현 된 것처럼 이기종 목록 사용의 좋은 예) 다른 예는 우선 순위 큐에 특정 메시지에 대한 리스너가 있고 책임 체인을 사용하는 메시지 디스패치의 경우, 디스패처는 메시지를 전달하고 메시지와 일치하는 첫 번째 핸들러는 메시지를 처리합니다.
반대쪽은 메시지를 등록하는 모든 사람에게 알리는 것입니다 (예 : MVVM 패턴에서 ViewModel의 느슨한 결합에 일반적으로 사용되는 이벤트 집 계기 패턴). 다음 구성을 사용합니다
IDictionary<Type, List<Object>>
사전에 추가하는 유일한 방법은 함수입니다
Register<T>(Action<T> handler)
(그리고 객체는 실제로 전달 된 핸들러에 대한 WeakReference입니다). 그래서 컴파일 타임에 닫힌 유형이 무엇인지 모르기 때문에 List <Object>를 사용해야합니다. 그러나 런타임에 사전의 키가되는 유형이되도록 강제 할 수 있습니다. 이벤트를 시작하고 싶을 때
Send<T>(T message)
다시 목록을 확인합니다. 어쨌든 캐스트해야하기 때문에 List <dynamic>을 사용하면 이점이 없습니다. 보시다시피 두 접근 방식에는 장점이 있습니다. Method overloading을 사용하여 객체를 동적으로 디스패치하려는 경우 dynamic이 수행 방법입니다. 관계없이 캐스팅을 강요 받았다면 Object를 사용할 수도 있습니다.