또한 확장 메서드가 C # 스타일로 사용될 때 Linq 쿼리를 더 쉽게 읽을 수 있도록 지원하는 방법으로 추가되었습니다.
이 두 가지 영향은 절대적으로 동일하지만 첫 번째는 훨씬 더 읽기 쉽습니다 (물론 더 많은 메서드를 연결하면 가독성의 격차가 증가합니다).
int n1 = new List<int> {1,2,3}.Where(i => i % 2 != 0).Last();
int n2 = Enumerable.Last(Enumerable.Where(new List<int> {1,2,3}, i => i % 2 != 0));
정규화 된 구문은 다음과 같아야합니다.
int n1 = new List<int> {1,2,3}.Where<int>(i => i % 2 != 0).Last<int>();
int n2 = Enumerable.Last<int>(Enumerable.Where<int>(new List<int> {1,2,3}, i => i % 2 != 0));
우연히, Where
및 의 유형 매개 Last
변수는이 두 메소드의 첫 번째 매개 변수 (키워드에 의해 도입되어 this
확장 메소드로 만드는 매개 변수)의 존재 덕분에 추론 될 수 있으므로 명시 적으로 언급 할 필요가 없습니다 .
이 점은 분명히 확장 메서드의 장점이며 메서드 체인이 관련된 모든 유사한 시나리오에서 이점을 얻을 수 있습니다.
특히, 어떤 서브 클래스에서든 기본 클래스 메서드를 호출 할 수 있고이 서브 클래스에 대한 강력한 형식의 참조 (서브 클래스 형식 사용)를 반환하는 것이 더 우아하고 설득력있는 방법입니다.
예 (좋아,이 시나리오는 완전히 치즈 맛이 없다) : 좋은 밤을 보낸 후 동물이 눈을 뜨고 울음을 터뜨린다. 모든 동물은 똑같은 방식으로 눈을 뜨고 개는 짖고 오리는 삑삑 거리는 소리를냅니다.
public abstract class Animal
{
}
public static class AnimalExtension
{
public static TAnimal OpenTheEyes<TAnimal>(this TAnimal animal) where TAnimal : Animal
{
return animal;
}
}
public class Dog : Animal
{
public void Bark() { }
}
public class Duck : Animal
{
public void Kwak() { }
}
class Program
{
static void Main(string[] args)
{
Dog Goofy = new Dog();
Duck Donald = new Duck();
Goofy.OpenTheEyes().Bark();
Donald.OpenTheEyes().Kwak();
}
}
개념적 OpenTheEyes
으로는 Animal
메서드 여야 하지만 그런 다음 Animal
특정 하위 클래스 메서드와 같은 Bark
또는 기타를 알지 못하는 추상 클래스의 인스턴스를 반환합니다 Duck
. * 1 및 * 2로 주석 처리 된 두 줄은 컴파일 오류를 발생시킵니다.
그러나 확장 메서드 덕분에 "호출되는 하위 클래스 유형을 알고있는 기본 메서드"와 같은 종류를 가질 수 있습니다.
간단한 제네릭 메서드로 작업을 수행 할 수 있지만 훨씬 더 어색한 방식으로 수행 할 수 있습니다.
public abstract class Animal
{
public TAnimal OpenTheEyes<TAnimal>() where TAnimal : Animal
{
return (TAnimal)this;
}
}
이번에는 매개 변수가 없으므로 반환 유형 추론이 불가능합니다. 호출은 다음과 같을 수 있습니다.
Goofy.OpenTheEyes<Dog>().Bark();
Donald.OpenTheEyes<Duck>().Kwak();
... 더 많은 체이닝이 포함되면 코드의 무게를 많이 측정 할 수 있습니다 (특히 유형 매개 변수가 항상 <Dog>
Goofy의 라인과 <Duck>
Donald의 라인에 있음을 알고 ...)