2012-05-17 4 views
0

익명 함수 매개 변수를 사용하는 메서드가 있습니다. 이 함수의 매개 변수는 지역 변수에 의해 제공됩니다.익명 함수 매개 변수의 범위를 제한하는 방법이 있습니까?

public void DoSomething<T>(Action<T> method) where T : new() 
{ 
    T instance = new T(); 
    method.Invoke(instance); 
} 

클로저 생성을 막고 싶습니다. DoSomething<T>이 완료되면 로컬 변수가 범위를 벗어납니다. 컴파일 시간에 그것을 제한하는 방법이 있습니까?

Foo capturedInstance = null; 
DoSomething<Foo>(item => capturedInstance = item); 
capturedInstance.Call(); 
+0

왜 필요한가요? 클로저에주의해야하는 외부 코드입니다. – SimpleVar

+0

@ YoryeNathan 맞습니다. 사용자에게 잘못된 것을하지 않고도 제한 할 수있는 방법이 있는지 궁금했습니다. –

+0

사용자는 항상 잘못된 행동을합니다. 프로그래머는 그를 확인하고 오류를 통해 그를 안내해야합니다. 그러나 다른 프로그래머들을 신뢰하는 것은 적어도 최소한 조금은해야 할 일입니다. 코드를 캡슐화하고 추상화 할 수 있습니다. – SimpleVar

답변

1

불행하게도 *, 그건 불가능 :

는 여기에 내가 피하고 싶은 상황입니다. 당신은 메소드가 그것의 주장으로 무엇을하는지에 대해 거의 통제 할 수 없습니다. 제네릭 형식을 사용하지 않는 경우에는 문제를 해결할 수 있지만 상황은 그렇게 걱정하지 않아도됩니다. (난 당신이 필요 없어 바랍니다.)


* 사실, 나는 그것을 "다행히"고려하십시오. 이것은 우리가 여기서 말하는 C++가 아닙니다.

-1

나는 코드가 이미 원하는대로한다고 생각합니다. 람다 item => capturedInstance = item을 나타내는 대리자는 DoSomething<Foo>에게만 전달되며 그 참조는 다른 사람에게 넘겨지지 않습니다. 따라서 포함 된 메서드가 끝나면 대리자는 범위를 벗어납니다. 그리고 람다 식으로 포착 된 지역 변수도 마찬가지입니다. 대리자에 대한 참조를 전달하는 경우에만 원하는 동작을 얻지 못합니다. T이 구조체이었다

+2

잘못되었습니다. 'DoSomething'을 실행 한 후 out-side 지역 변수가 변경 될 것입니다. 즉,'Action'/lambda 표현식이하는 것처럼, 그가 막으려 고하는 것입니다. 그는 델리게이트가 "범위 안에"있을 필요는 없으며, 실행 후 "captureInstance"를 "롤백"시키거나 일부 체크 나 제약 조건에 의해 캡슐 인스턴스를 변경하지 않도록합니다. – SimpleVar

1

경우, 필드 또는 외부 방법에 ref 파라미터로 배열 요소를 통과 형 T 필드 또는 유형 T[]의 배열을 유지 코드 가능한 것; 그 메소드는 구조체의 임시 복사본을 만들 필요없이 해당 필드 나 배열 슬롯에서 직접 효율적으로 작동 할 수 있지만 일단 메소드가 반환되면 필드 또는 배열을 보유하는 유형이 외부 코드가 더 이상 해당 슬롯에 액세스 할 수 없다고 확신 할 수 있습니다 . Outside는 물론 필드 나 요소의 내용을 복사 할 수 있지만 구조체를 보유하는 유형이 다시 외부 코드에 노출 될 때까지 원본을 변경할 수 없습니다.

불행히도 T이 가변 클래스 인 경우 참조를 표시하면 외부 코드가 무작위로 복사하여 해당 참조를 영원히 통과 할 수 있습니다. 이러한 이유 때문에, 변경 가능한 클래스는 변경 가능한 구조체보다 훨씬 나쁜 데이터 홀더입니다. 외부 참조가 직접 참조를 노출시키지 않고 클래스를 사용하도록 허용하려면 래퍼 클래스와 인터페이스를 만들어야합니다. 불행히도 실제로는 무서운 양의 중복 된 코드를 사용하거나 Reflection을 사용하여 런타임에 래퍼를 생성하지 않고도이 작업을 수행 할 수 없습니다.

관련 문제