program tip

C #에서 람다 변수의 범위는 무엇입니까?

radiobox 2020. 11. 16. 08:05
반응형

C #에서 람다 변수의 범위는 무엇입니까?


람다 변수의 범위에 대해 혼란 스럽습니다. 예를 들면 다음과 같습니다.

var query = 
    from customer in clist
    from order in olist
    .Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==  // line 1
        olist.Where(o1 => o1.CustomerID == customer.CustomerID)        // line 2
             .Max(o1 => o1.OrderDate)                                  // line 3
    )
    select new {
        customer.CustomerID,
        customer.Name,
        customer.Address,
        order.Product,
        order.OrderDate
    };

1 행에서 람다 변수 'o'를 선언했습니다. 이는 2 행에서 다시 선언 할 수 없음을 의미합니다 (또는 적어도 컴파일러가 시도하면 불평 함).하지만 'o1'이 이미 존재하더라도 3 행에 대해 불평하지 않습니다. ??

람다 변수의 범위는 무엇입니까?


대괄호는 단서를 제공합니다. 람다 변수는 선언 된 범위에서 캡처됩니다.

.Where(o => ... olist.Where(o1 => ...).Max(o1 => ...))
  //  |----------------------------------------------| scope of o
  //                       |---------|                 scope of first o1
  //                                      |---------|  scope of second o1

o1변수에 대해 겹치는 부분이 없지만 둘 다 o변수와 겹치거나 음영 처리 되므로 동일한 이름을 사용할 수 없습니다.


람다 매개 변수의 범위는 내부 람다 식 또는 범위를 포함하여 람다 식 본문의 전체 범위와 같습니다.

람다 식의 구문을 확장하고 친숙한 들여 쓰기를 추가하면 더 명확해질 수 있습니다 (아마도 yamen의 다이어그램 답변 만큼 명확하지는 않습니다 !).

.Where(o => {
    return o.CustomerID == customer.CustomerID
        && o.OrderDate == olist.Where(
            o1 => o1.CustomerID == customer.CustomerID
        )
        .Max(
            o1 => o1.OrderDate
        );
})

귀하의 통지 .Where().Max()호출이 외부에 위치해 있습니다 .Where(). o외측 람다 (이 호출된다 내면 람다 내 외측 람다로 캡슐화 폐쇄 이미 내면 람다의 범위에 있는지 등), 및 파라미터로서 재사용 할 수 없다.

o1두 개의 내부 람다가 서로 완전히 분리되어 있기 때문에 재사용 할 수 있으므로 둘 중 하나의 범위를 벗어나지 않습니다.


범위 중 하나에 다른 범위가 포함 된 경우 두 범위에서 동일한 변수 이름을 사용할 수 없습니다.

귀하의 질문에서는 o외부 범위에 도입되었으므로 두 번째 Where()또는에서 다시 사용할 수 없습니다. Max()이러한 범위는 외부 범위에 포함되어 있기 때문입니다.

반면에 o1하나는 다른 하나를 포함하지 않기 때문에 두 내부 범위 모두에서 사용할 수 있으므로 모호성이 없습니다.


lamda는 코드에서 익명 함수를 대체하기 때문에

동일한 범위

Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==   //line 1
         olist.Where(o1 => o1.CustomerID == customer.CustomerID)   //line 2     

변수 "o"가 존재하는 기능의 범위입니다.

여기 세 번째 줄에서 이것은 변수의 새로운 스 크롭, 즉 새로운 함수 범위입니다.

다른 범위

  .Max(o1 => o1.OrderDate)   )        //line 3

따라서 line1 및 line2의 공명입니다. line1에 정의 된 varialbe "o"는 동일한 스 크롭으로 인해 line2에서 정의 할 수 없으며 line2에 정의 된 "o1"은 다른 기능 범위에 있으므로 line3에서 다시 정의 할 수 있습니다.


C #은 이와 같은 섀도 잉을 지원하지 않습니다.

이유 o1는 다시 작동합니다 o1. 이전 .


다른 변수와 동일합니다. 의 범위는 o첫 번째의 전체 표현식 Where이므로 첫 번째 안에있는 두 번째에서 다시 사용할 수 없습니다. 그러나 범위는 o1두 번째 표현 일 뿐이 Where므로 Max두 번째 외부 에있는 표현에서 사용할 수 있습니다 Where. 코드에서 :

// o scope lasts until the first bracket is closed
Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==
// o1 scope lasts until the second bracket is closed; the first is not yet closed here
        olist.Where(o1 => o1.CustomerID == customer.CustomerID)
// The second bracket is closed, so o1 is already out of scope; o is still in scope
             .Max(o1 => o1.OrderDate)
)
// The first bracket is closed, so o is finally out of scope

나는 당신의 코드에 따라 이렇게 상상해보십시오 ...

.Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==  // line 1
        olist.Where(o1 => o1.CustomerID == customer.CustomerID)        // line 2
             .Max(o1 => o1.OrderDate)                                  // line 3
    )

설명의 조잡한 방법이지만 대괄호가 범위를 결정합니다. 두 번째 o1은 두 번째 안에 중첩되지 않습니다. 그렇지 않으면 동일한 문제가 발생합니다.

//outermost where

((BEGIN-o

//inner where

(BEGIN-o1 END-o1)

//max

(BEGIN-o1 END-o1)

END-o))

var external = 1;

//This is a scope
Action scope = new Action(() =>
{
    //myVar is not accessible from outside
    var myVar = 0 + external;
    Console.WriteLine(myVar); //outputs 1
});

//Call the scope
scope();
//Console.WriteLine(myVar);//Will not compile

코드가 컴파일되면 Action에서 선언 된 void의 모든 논리가 ()=>{ ... }이름이 엉망인 형식의 메서드로 이동됩니다.

The run time will call the newly created function when it is reaches that place on the stack.

You can pass values into a scope / lambda in various ways which is the same for getting them out.

Variables declared in a lambda are not accessible outside with their declared name.

It is also possible to utilize reflection to pull out the mangled name however I am not sure you require that. (Please let me know if I am wrong.)

참고URL : https://stackoverflow.com/questions/10494074/what-is-the-scope-of-a-lambda-variable-in-c

반응형