문제

이것은 단지 호기심 질문 일뿐입니다.

.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 - 용어를 이해할 필요가 없습니다. 내 진실 테스트를 적용하십시오.

"술어"의 경우 이것은 괜찮을지 모르지만 표준화하려는 시도에 감사드립니다. 또한 해당 영역의 관련 방법과 많은 패리티를 허용합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top