문제
이것은 단지 호기심 질문 일뿐입니다.
.NET Framework 클래스 라이브러리에는 예를 들어이 두 가지 방법이 있습니다.
public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate
)
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
왜 그들은 사용합니까? Func<TSource, bool>
대신에 Predicate<TSource>
? 그런 것 같습니다 Predicate<TSource>
만 사용됩니다 List<T>
그리고 Array<T>
, 동안 Func<TSource, bool>
거의 모든 것에 의해 사용됩니다 Queryable
그리고 Enumerable
방법과 확장 방법 ... 그게 무슨 일이야?
해결책
하는 동안 Predicate
동시에 소개되었습니다 List<T>
그리고 Array<T>
, .NET 2.0에서, 다른 Func
그리고 Action
변형은 .NET 3.5에서 나옵니다.
그래서 그 것들 Func
Predicates는 주로 LINQ 연산자의 일관성을 위해 사용됩니다. .NET 3.5 기준, 사용에 관한 Func<T>
그리고 Action<T>
그만큼 가이드 라인 상태:
새로운 LINQ 유형을 사용하십시오
Func<>
그리고Expression<>
사용자 정의 대표와 선임자 대신
다른 팁
나는 이것을 전에 궁금했다. 나는 좋아한다 Predicate<T>
대표 - 훌륭하고 설명 적입니다. 그러나 과부하를 고려해야합니다 Where
:
Where<T>(IEnumerable<T>, Func<T, bool>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
이를 통해 항목 색인을 기반으로 필터를 필터링 할 수 있습니다. 그것은 훌륭하고 일관되지만 :
Where<T>(IEnumerable<T>, Predicate<T>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
그렇지 않을 것입니다.
분명히 사용의 실제 이유입니다 Func
특정 대표 대신 C#은 대의원을 완전히 다른 유형으로 개별적으로 선언한다는 것입니다.
일지라도 Func<int, bool>
그리고 Predicate<int>
둘 다 동일한 인수와 반환 유형을 가지고 있으며, 과제와 호환되지 않습니다. 따라서 모든 라이브러리가 각 대의원 패턴에 대해 자체 대의원 유형을 선언 한 경우, 사용자가 "브리징"대의원을 삽입하지 않는 한 해당 라이브러리는 상호 운용 할 수 없습니다.
// declare two delegate types, completely identical but different names:
public delegate void ExceptionHandler1(Exception x);
public delegate void ExceptionHandler2(Exception x);
// a method that is compatible with either of them:
public static void MyExceptionHandler(Exception x)
{
Console.WriteLine(x.Message);
}
static void Main(string[] args)
{
// can assign any method having the right pattern
ExceptionHandler1 x1 = MyExceptionHandler;
// and yet cannot assign a delegate with identical declaration!
ExceptionHandler2 x2 = x1; // error at compile time
}
Microsoft는 모든 사람이 FUNC를 사용하도록 장려함으로써 양립 할 수없는 대의원 유형의 문제를 완화하기를 희망합니다. 모든 사람의 대표는 매개 변수/반환 유형에 따라 일치하기 때문에 잘 재생됩니다.
모든 문제를 해결하는 것은 아닙니다 Func
(그리고 Action
) 가질 수 없습니다 out
또는 ref
매개 변수이지만 덜 일반적으로 사용됩니다.
업데이트: 의견에서 svish는 다음과 같이 말합니다.
그럼에도 불구하고 매개 변수 유형을 func에서 술어 및 뒤로 전환하는 것은 아무런 차이가없는 것 같습니다. 적어도 여전히 문제없이 컴파일합니다.
예, 귀하의 프로그램이 내 첫 줄에서와 같이 귀하의 프로그램 만 대의원에게 방법을 할당하는 한 Main
기능. 컴파일러는 방법으로 전달되는 새로운 대의원 객체에 대한 코드를 조용히 생성합니다. 그래서 내 Main
기능, 변경할 수 있습니다 x1
유형이 될 수 있습니다 ExceptionHandler2
문제를 일으키지 않고.
그러나 두 번째 줄에서는 첫 번째 대의원을 다른 대의원에게 할당하려고합니다. 두 번째 대표 유형이 정확히 동일한 매개 변수와 반환 유형을 가지고 있다고 생각조차도, 컴파일러는 오류가 발생합니다. CS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'
.
어쩌면 이것은 더 명확하게 만들 것입니다 :
public static bool IsNegative(int x)
{
return x < 0;
}
static void Main(string[] args)
{
Predicate<int> p = IsNegative;
Func<int, bool> f = IsNegative;
p = f; // Not allowed
}
내 방법 IsNegative
할당하는 것은 완벽하게 좋은 것입니다 p
그리고 f
내가 직접 그렇게하는 한 변수. 그러나 그 변수 중 하나를 다른 변수에 할당 할 수 없습니다.
조언 (3.5 이상)은 Action<...>
그리고 Func<...>
- "왜?" - 한 가지 장점은 "Predicate<T>
""술어 "가 무엇을 의미하는지 아는 경우에만 의미가 있습니다. 그렇지 않으면 Signatute를 찾기 위해 객체 브라우저 (등)를 봐야합니다.
거꾸로 Func<T,bool>
표준 패턴을 따릅니다. 나는 이것이 바로 T
그리고 반환 a bool
- 용어를 이해할 필요가 없습니다. 내 진실 테스트를 적용하십시오.
"술어"의 경우 이것은 괜찮을지 모르지만 표준화하려는 시도에 감사드립니다. 또한 해당 영역의 관련 방법과 많은 패리티를 허용합니다.