source

람다 특성 값 선택기(파라미터)

manysource 2023. 5. 10. 22:07

람다 특성 값 선택기(파라미터)

주어진 속성의 값을 반환하기 위해 내부 객체에 사용될 람다 식을 사용할 추가 매개 변수가 있도록 메서드를 수정해야 합니다.LINQ 표현에 대한 저의 첫 시도이기 때문에 용어의 잘못된 사용을 용서하십시오!

답을 했듯이, 제 것 가 찾을 수 있는 하거나, 기능에 대한 표현들을 다루는 것 같습니다..Where()제가 잘 알고 있는 것입니다.

지금까지 사용한 내용(컷 버전):

class MyClass
{
    private MyObject _myObject = new MyObject() { Name = "Test", Code = "T" };

    private string MyMethod(int testParameter, ??? selector)
    {
        //return _myObject.Name;
        //return _myObject.Code;
        return ???;
    }
}

저는 이것을 다음과 같이 부르고 싶습니다.

string result = _myClassInstance.MyMethod(1, (x => x.Name));

또는:

string result = _myClassInstance.MyMethod(1, (x => x.Code));

제가 있는 은 분히제놓있부는은분고치가명입니다.selector 변수는 의매변수에 있습니다.MyMethod로컬 변수에 적용하는 방법 및 호출할 때 필요한 속성을 메서드에 전달하는 방법.

도움을 주시면 감사하겠습니다. 또한 VB에 대한 추가 보너스 포인트도 제공됩니다.불행히도 최종 구현은 NET 솔루션뿐 아니라 우리의 유일한 VB 프로젝트에 있어야 합니다!

private string MyMethod(int testParameter, Func<MyObject, string> selector)
{
    return selector(_myObject);
}

을 할 때Func마지막 매개 변수는 반환 형식이고 첫 번째 N-1은 인수 형식입니다.이 경우에는 단일 항목이 있습니다.MyObject에 대한 인수입니다.selector그리고 그것은 a를 반환합니다.string.

다음과 같이 호출할 수 있습니다.

string name = _myClassInstance.MyMethod(1, x => x.Name);
string result = _myClassInstance.MyMethod(1, x => x.Code);

이 의반유 형이후환후▁the.MyMethod의 의반일환다합의 반환 형식과 합니다.selector일반적으로 만들 수 있습니다.

private T MyMethod<T>(int testParameter, Func<MyObject, T> selector)
{
    MyObject obj = //
    return selector(obj);
}

VB 몰라요.순이지만 다음과 같이 보입니다.

Public Function MyMethod(testParameter as Integer, selector as Func(Of MyObject, String))
    Return selector(_myObject)
End Function

일반 버전은 다음과 같습니다.

Public Function MyMethod(Of T)(testParameter as Integer, selector Func(Of MyObject, T))
    Return selector(_myObject)
End Function

매우 유연한 다른 접근 방식을 보여드리겠습니다(하단의 DotNetFiddle 참조).자신만의 LINQ 함수를 쉽게 작성하여 기존 함수를 확장하거나 자신만의 함수를 작성할 수 있으며 LINQ 쿼리의 기능을 활용할 수 있습니다.

이 예에서는 Linq의 기능을 개선하고 있습니다.Distinct그룹화에 사용되는 필드를 지정할 수 있는 기능을 제공합니다.

용도(예):

var myQuery=(from x in Customers select x).MyDistinct(d => d.CustomerID);

를 " " " " " "로 .CustomerID각 그룹의 첫 번째 요소가 반환됩니다.

선언의 MyDistinct:

public static class Extensions
{
    public static IEnumerable<T> MyDistinct<T, V>(this IEnumerable<T> query, 
                                                    Func<T, V> f)
    {
        return query.GroupBy(f).Select(x=>x.First());
    }
}

은 그것을 볼 수 .f두 번째 매개 변수는 다음과 같이 선언됩니다.Func<T, V>그래서 그것은 사용될 수 있습니다..GroupBy진술.


질문의 코드로 돌아갑니다. 선언한 경우

class MyObject
{
    public string Name;
    public string Code;
}

private MyObject[] _myObject = {
    new MyObject() { Name = "Test1", Code = "T"},
    new MyObject() { Name = "Test2", Code = "Q"},
    new MyObject() { Name = "Test2", Code = "T"},
    new MyObject() { Name = "Test5", Code = "Q"}
};

당신은 그것을 새롭게 정의된 기능과 함께 사용할 수 있습니다.MyDistinct다음과 같이:

var myQuery = (from x in _myObject select x).MyDistinct(d => d.Code);

돌아올 것입니다.

이름 코드
테스트 1 T
테스트 2 Q

또는 사용할 수 있습니다..MyDistinct(d => d.Name)쿼리에서 다음을 반환합니다.

이름 코드
테스트 1 T
테스트 2 Q
테스트 5 Q

주목할 점은MyDistinct제네릭과 함께 선언됩니다.T그리고.V올바른 개체 유형을 자동으로 인식하여 사용하고 반환합니다.MyObject요소들.


고급 사용

주의:MyDistinct항상 각 그룹의 첫 번째 요소를 사용합니다.필요한 요소를 정의하는 조건이 필요하면 어떻게 합니까?

다음과 같은 방법이 있습니다.

public static class Extensions
{
    public static IEnumerable<T> MyDistinct<T, V>(this IEnumerable<T> query,
                                                    Func<T, V> f, 
                                                    Func<IGrouping<V,T>,T> h=null)
    {
        if (h==null) h=(x => x.First());
        return query.GroupBy(f).Select(h);
    }
}

이 수정을 통해 이전과 동일하게 사용할 수 있습니다. 즉, 다음과 같은 매개 변수를 하나 지정합니다..MyDistinct(d => d.Name)그러나 다음과 같은 조건을 지정할 수도 있습니다.x => x.FirstOrDefault(y => y.Name.Contains("1")||y.Name.Contains("2"))다음과 같은 두 번째 매개 변수로 사용할 수:

var myQuery2 = (from x in _myObject select x).MyDistinct(d => d.Name,
        x=>x.FirstOrDefault(y=>y.Name.Contains("1")||y.Name.Contains("2"))
        );

이 쿼리를 실행하면 결과는 다음과 같습니다.

이름 코드
테스트 1 T
테스트 2 Q
무효의

왜냐면Test5조건을 충족하지 않습니다(1 또는 2를 포함하지 않음). 세 번째 행에서 null이 됩니다.

참고: 조건만 노출하려면 다음과 같이 구현하면 훨씬 더 간단합니다.

public static IEnumerable<T> MyDistinct2<T, V>(this IEnumerable<T> query,
                                                Func<T, V> f,
                                                Func<T,bool> h=null
                                                )
{
    if (h == null) h = (y => true);
    return query.GroupBy(f).Select(x=>x.FirstOrDefault(h));
}

이 경우 쿼리는 다음과 같습니다.

var myQuery3 = (from x in _myObject select x).MyDistinct2(d => d.Name,
                    y => y.Name.Contains("1") || y.Name.Contains("2")
                    );

그래서 당신은 쓸 필요가 없습니다.x=>x.FirstOrDefault(... condition ...).

DotNetFiddle에서 사용해 보십시오.

C#로

Func를 찾고 있는 매개 변수 유형

private string MyMethod(int testParameter, Func<MyClass,string> selector){
    return selector(_myObject);
}

여전히 Func를 원하는 VB에서는 구문이 조금 다릅니다.

Function MyMethod(ByVal testParameter As Integer, ByVal selector as Func(Of MyClass,string) as string
    return selector(_myObject)
End Function
class MyClass
{
    private MyObject _myObject = new MyObject() { Name = "Test", Code = "T" };

    private string MyMethod(int testParameter, Func<MyObject, string> selector)
    {
        return selector(_myObject );
    }
}

선택기의 대리인을 통해 이 작업을 수행할 수 있습니다.

delegate string SampleDelegate(MyObject obj);

private string MyMethod(int testParameter, SampleDelegate selector)
{
    return selector(_myObject);
}

대리자 클래스(VB의 경우 "대리자", C#의 경우 "대리자") 또는 해당 하위 유형 중 하나를 찾고 있을 수 있습니다.

페이지에는 특히 페이지 하단 근처에서 유용하게 사용할 수 있는 몇 가지 예제가 있습니다.

다음은 수행하고자 하는 작업에 대한 VB 예입니다.

Public Class MyClass

  Private Property _myObject As MyObject = New MyObject With {.Name = "Test", .Code = "T"}

  Private Function MyMethod(testParameter As Integer, selector As Func(Of MyObject, String)) As String
    Return selector(_myObject).ToString
  End Function

End Class

언급URL : https://stackoverflow.com/questions/16676854/lambda-property-value-selector-as-parameter