람다 함수를 선언하고 즉시 호출 할 수 있습니다.
Func<int, int> lambda = (input) => { return 1; };
int output = lambda(0);
한 줄로 할 수 있는지 궁금합니다.
int output = (input) => { return 1; }(0);
컴파일러 오류 “방법 이름 예상”을 제공합니다. 전송 Func<int, int>
이 작동하지 않습니다.
int output = (Func<int, int>)((input) => { return 1; })(0);
동일한 오류가 발생하며 아래에 언급 된 이유로 입력 인수 유형 (첫 번째 int
) 을 명시 적으로 지정하지 않아도됩니다 .
예를 들어 코드를 직접 삽입하는 대신 왜 내가 이것을하고 싶은지 궁금 할 것입니다 int output = 1;
. 이유는 다음과 같습니다.로 SOAP 웹 서비스에 대한 참조를 svcutil
생성했습니다. 그래서 대신
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = CreateAddress(sh.ReceiverAddress_Shipment);
}).ToArray()
};
별도의 CreateAddress(GetOrderResultOrderShipment_OrderShipmentShipment_Address address)
방법 (실제 이름은 더 길고 양식에 대한 제어가 매우 제한적입니다), 작성하고 싶습니다
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = sh.ReceiverAddress_Shipment == null ? null : () => {
var a = sh.ReceiverAddress_Shipment.Address;
return new Address {
Street = a.Street
...
};
}()
}).ToArray()
};
내가 쓸 수 있다는 것을 안다
Address = sh.ReceiverAddress_Shipment == null ? null : new Address {
Street = sh.ReceiverAddress_Shipment.Address.Street,
...
}
그러나 sh.ReceiverAddress_Shipment.Address
필드가 많으면 그 부분 조차 매우 반복적입니다. 람다를 선언하고 즉시 호출하면 문자를 쓰는 것이 더 우아 합니다.
답변
람다를 캐스팅하는 대신 작은 도우미 함수를 사용하는 것이 좋습니다.
public static TOut Exec<TIn, TOut>(Func<TIn, TOut> func, TIn input) => func(input);
다음과 같이 사용할 수 있습니다 int x = Exec(myVar => myVar + 2, 0);
.. 이것은 여기에 제안 된 대안보다 훨씬 좋습니다.
답변
추악하지만 가능합니다.
int output = ((Func<int, int>)(input => { return 1; }))(0);
캐스트 할 수 있지만 람다는 괄호로 묶어야합니다.
위의 내용도 단순화 할 수 있습니다.
int output = ((Func<int, int>)(input => 1))(0);
답변
C #의 Lambda 리터럴은 그 의미가 유형에 따라 다르다는 점에서 호기심이 있습니다. 그들은 반환 유형에 본질적으로 과부하 되어 C #의 다른 곳에는 존재하지 않습니다. (숫자 리터럴은 다소 유사합니다.)
동일한 람다 리터럴을 수행 할 수 있습니다 중 하나를 당신이 실행할 수있는 익명 함수 (즉,로 평가 Func
/ Action
) 또는 종류 (즉, LINQ 표현 나무)는 추상 구문 트리 등으로, 몸의 내부 운영의 추상적 인 표현입니다.
후자는 예를 들어 LINQ to SQL, LINQ to XML 등의 작동 방식입니다. 람다 는 실행 코드로 평가 하지 않고 LINQ Expression Tree로 평가 한 다음 LINQ 공급자는 해당 Expression Tree를 사용하여 람다의 본문은 수행하고 예를 들어 SQL 쿼리를 생성합니다.
귀하의 경우 컴파일러가 람다 리터럴이 Func
LINQ 식 으로 평가되는 것을 알 수있는 방법이 없습니다 . Johnathan Barclay의 답변이 작동하는 이유 는 람다 식에 유형을 제공하므로 컴파일러는 내부 코드 를 나타내는 평가되지 않은 LINQ 식 트리 대신 람다의 본문 Func
을 실행 하는 컴파일 된 코드를 원한다는 것을 알고 있습니다. 람다의 몸.
답변
당신은의 선언을 인라인 수 Func
수행하여
int output = (new Func<int, int>(() => { return 1; }))(0);
즉시 호출합니다.
답변
Select
메소드 에서 별명을 작성할 수도 있습니다.
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order == null ? new Shipment[0]
o.Shipment_Order.Select(sh => {
var s = sh.ReceiverAddress_Shipment;
var a = s.Address;
return new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = s == null ?
null :
new Address {
Street = a.Street
...
}
};
}).ToArray()
};
또는 ??
운영자 와
var o = await client.GetOrderAsync(request);
return new Order {
OrderDate = o.OrderDate,
...
Shipments = o.Shipment_Order?.Select(sh => {
var s = sh.ReceiverAddress_Shipment;
var a = s.Address;
return new Shipment {
ShipmentID = sh.ShipmentID,
...
Address = s == null ?
null :
new Address {
Street = a.Street
...
}
};
}).ToArray() ?? new Shipment[0]
};
답변
확장 방법 설계 지침 몇 가지를 위반하지 않는다면 null 조건부 연산자와 결합 된 확장 방법 ?.
을 사용하면 합리적으로 멀리 갈 수 있습니다.
public static class Extensions
{
public static TOut Map<TIn, TOut>(this TIn value, Func<TIn, TOut> map)
where TIn : class
=> value == null ? default(TOut) : map(value);
public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> items)
=> items ?? Enumerable.Empty<T>();
}
당신에게 이것을 줄 것입니다 :
return new Order
{
OrderDate = o.OrderDate,
Shipments = o.Shipment_Order.OrEmpty().Select(sh => new Shipment
{
ShipmentID = sh.ShipmentID,
Address = sh.ReceiverAddress_Shipment?.Address.Map(a => new Address
{
Street = a.Street
})
}).ToArray()
};
대부분 배열이 필요한 경우 ToArray
확장 메서드를 재정 의하여 몇 가지 메서드 호출을 캡슐화하십시오.
public static TOut[] ToArray<TIn, TOut>(this IEnumerable<TIn> items, Func<TIn, TOut> map)
=> items == null ? new TOut[0] : items.Select(map).ToArray();
를 야기하는:
return new Order
{
OrderDate = o.OrderDate,
Shipments = o.Shipment_Order.ToArray(sh => new Shipment
{
ShipmentID = sh.ShipmentID,
Address = sh.ReceiverAddress_Shipment?.Address.Map(a => new Address
{
Street = a.Street
})
})
};