2011-01-24 1 views
3

나는 this 질문을 읽기,이 응답클로저 내에 잠글 수 있습니까()? Lambdas와 코드 출력은 어떻게 생겼습니까?

이 실제로 환상적인 기능입니다을 읽었습니다. 이렇게하면 은 일반적으로 숨겨진 무언가에 액세스하고, 은 개인 클래스 변수라고 말하면서 이 이벤트에 대한 응답으로 을 제어 된 방식으로 조작하도록 할 수 있습니다.

변수 을 쉽게 시뮬레이션 할 수 있으며 변수 의 로컬 복사본을 만들어이를 사용합니다.

이 상황에서 Lock()을 구현해야합니까?

어떻게 생겼습니까?

에릭 Lippert의에 따르면 컴파일러하게 this과 같은 코드의 모양을

람다가 긴 형태의 코드뿐만 아니라, 같을 것이다 무엇
private class Locals 
{ 
    public int count; 
    public void Anonymous() 
    { 
    this.count++; 
    } 
} 

public Action Counter() 
{ 
    Locals locals = new Locals(); 
    locals.count = 0; 
    Action counter = new Action(locals.Anonymous); 
    return counter; 
} 

?

+0

뮤텍스와 클로저는 주로 직각 개념입니다. – Ani

+0

나는 그것이 다르다는 것을 알 수있다.나를 던지고있는 것은 3 가지 일이 벌어지고 있다는 것입니다 : 대표단/이벤트, 클로저, 그리고 람다 내의 하나 이상의 진술. 내가 본 모든 예제는 한 줄짜리 람다 (lambda) 다. 그리고 내가 찾을 수있는 많은 예제를보고있다. – TLDR

답변

5

이있는 경우 잠금을 설정해야합니다. 그렇다면 클로우저에 lock 문을 넣는 것을 막을 수있는 방법은 없습니다.

예를 들어, 당신이 할 수 있습니다 :

public static Action<T> GetLockedAdd<T>(IList<T> list) 
{ 
    var lockObj = new object(); 
    return x => 
    { 
     lock (lockObj) 
     { 
      list.Add(x); 
     } 
    } 
} 

이 컴파일러가 생성 된 코드의 관점에서, 어떤 모습입니까? 자문 해보십시오 : 무엇이 캡처 되었습니까?

  • 로컬 잠금 object입니다.
  • IList<T> 전달.

이는 컴파일러가 생성 한 클래스의 인스턴스 필드로 캡처됩니다. 결과는 다음과 같습니다.

class LockedAdder<T> 
{ 
    // This field serves the role of the lockObj variable; it will be 
    // initialized when the type is instantiated. 
    public object LockObj = new object(); 

    // This field serves as the list parameter; it will be set within 
    // the method. 
    public IList<T> List; 

    // This is the method for the lambda. 
    public void Add(T x) 
    { 
     lock (LockObj) 
     { 
      List.Add(x); 
     } 
    } 
} 

public static Action<T> GetLockedAdd<T>(IList<T> list) 
{ 
    // Initializing the lockObj variable becomes equivalent to 
    // instantiating the generated class. 
    var lockedAdder = new LockedAdder<T> { List = list }; 

    // The lambda becomes a method call on the instance we have 
    // just made. 
    return new Action<T>(lockedAdder.Add); 
} 

의미가 있습니까?

2

예 가능합니다.

잠긴 개체 인스턴스를 변경하지 않도록하십시오. 그렇지 않으면 쓸모가 없습니다.

static Func<int> GetIncrementer() 
{ 
    object locker = new object(); 
    int i = 0; 
    return() => { lock (locker) { return i++; } }; 
} 

당신이 그것을 호출 할 때, 그것은 스레드 안전 방식으로 내부 카운터를 증가 함수를 반환합니다

+0

잠긴 것을 돌연변이시킬 수있는 잠금의 전체 지점이 아닌가? "잠금 해제 된 객체를 변경하지 마십시오"라는 뜻입니까? – Gabe

+0

@Gabe : 나는'Monitor.Enter'에 전달되는 객체 인스턴스를 참조합니다. – leppie

1

는이 같은 기능을 가질 수있다. 이러한 기능을 구현하는 가장 좋은 방법은 아니지만 클로저 내부에 잠금 장치가 있음을 보여줍니다.

+0

그래서 공백은 중요하지 않으며, 원하는 코드를 람다에 넣을 수 있습니까? 나는 지금 ... – TLDR

+0

@EnduroUSATour : 아니오, 공백은 C#에서는 중요하지 않습니다. 하나 이상의 표현식을 가지고 있다면, 그 주위에 중괄호를 넣고'return'을 사용하면 닫는 함수가 원하는만큼 복잡해질 수 있습니다. – Gabe