2016-10-19 5 views
3

궁금합니다. 다음 코드 스 니펫이 두 번째 메모리보다 많은 메모리를 사용합니까?익명 함수는 루프에서 더 많은 메모리를 사용합니까

List<Action> myList = new List<Action>(); 
for(int i = 0; i < 10000; i++) 
{ 
    myList.Add(() => { /* Code */}); 
} 

이번에는 방법을 가리 킵니다.

List<Action> myList = new List<Action>(); 
for (int i = 0; i < 10000; i++) 
{ 
    myList.Add(myFuntion); 
} 

void myFuntion()... 

첫 번째 코드 조각이 익명 메소드를 저장해야하기 때문에 더 많은 메모리를 사용하는지 궁금합니다. 아니면이 같은 익명 함수에 때마다

을 가리키는 그리고 함수에 두 번째 코드 포인트를 수행하거나 때마다 전체 기능을

감사

+0

일반적으로 컴파일러는 람다를위한 델리게이트를 생성합니다 - 런타임에는 일반적인 방법과 다르지 않습니다 ... 여기에 몇 가지 예외가있을 수 있습니다. –

+0

분석> 성능 프로파일 러> 메모리 사용량 확인> 시작> 스냅 샷 찍기> 프로그램 종료로 이동하여 결과를 확인하십시오. 심지어 폐쇄의 경우 –

답변

2

I가 말할 수를 저장 않습니다이다. NET을 확실히하지만 익명 함수 (예 : myList 귀하의 예제에서 항복 기능에서 모든 요소를 ​​캡처하는 경우)에 따라 다릅니다 일반적으로 다릅니다. 그렇지 않은 경우 컴파일러에서 컴파일러가 생성 한 이름이있는 일반 정적 함수로 변경할 수 있습니다.

뭔가를 캡처하면 컴파일러는 캡처 된 변수를 저장하고 컴파일러 생성 함수의 인수로 사용하는 추가 데이터 구조를 생성하고 할당해야합니다. 예 : 당신이 myList.Add(() => { var z = myList.Count; .... });을 할 경우 컴파일러는이 같은 무언가를 생성해야 :

class GenertedEnv 
{ 
    public List<Action> myList; 
} 

static void AnonymousFunction(GeneratedEnv env, /* Plus other lambda parameters*/) 
{ 
    var z = env.myList.Count; 
    ... 
} 
+0

는, 컴파일러가 폐쇄 변수 구성원이 포함 (당신을 위해 업데이트를 유지) 클래스를 생성 - http://tryroslyn.azurewebsites.net/#K4Zwlgdg5gBAygTxAFwKYFsB0AZSBHAbgChRJZEUNMBhAewBt7UBjZMWiETAcVQlQBOYZsVLR4SNOmJEADsABG9YTGb0AhiBAwAYrVowA3kSIwzMeUpUp1bZjAButMABMYAWXWQAFAEojRACQgbgoADwAgqzsEAB8MOgIocgwALww/ADuMMmR0RyxfsTBAGa0At6QKWBpMAAMBDA1YTAAjHUdDU0A1N2+QYHG5sGBicmYES4u3n5p8YYwdJwMqJgA6kJouPzeAEQAcsDoCoIwuzDdTb4EAL7XAzdBjzdAA ([여기]를 참조 ==). "런타임 메소드 생성"이 필요하지 않습니다. –

+0

A [나은 예 (http://tryroslyn.azurewebsites.net/#K4Zwlgdg5gBAygTxAFwKYFsB0AZSBHAbgChRJZEUNMBhAewBt7UBjZMWiETAcVQlQBOYZsVLR4SNOmJEADsABG9YTGb0AhiBAwAYrVowA3kSIwzMeUpUp1bZjAButMABMYAWXWQAFAEojRACQgbgoADwAgqzsEAB8MOgIocgwALww/ADuMMmR0RyxfsTBAGa0At6QKWBpMAAMBDA1YTAAjHUdDU0A1N2+QYHG5sMjDuoCMAAetWDE5sGBicmYES4u3n5p8YYwdJwMqJgA6kJouPzeAEQAcsDoCoIwlzDdU74EAL7vpiO/P7/DSa9YqBD5BMEfIA=) 변수의 값이 변경 될 때 반원 업데이트되는 방법을 보여. –

+0

나는 여기서 컴파일러가 런타임에 생성되는 것이 아니라 클래스와 함수를 생성한다고 말하고 싶다. 하지만 예, 링크에서 디 컴파일 된 코드는 컴파일러가 실제로 무엇을하는지 시각화하는 데 도움이됩니다. – Matthias247

2

첫 번째 방법을 사용하면 목록에 추가하고있는 Action 위임에 그 방법을하는 방법으로 내부 클래스를 생성하고 할당합니다.
그러나 한 번의 작업을 인스턴스화하고 매번 목록에 추가하는 것으로 보입니다.
자료 : tryroslyn

번째 방법은 때문에 모든 루프에 새로운 작업을 인스턴스화

list.Add(new Action(MyFunction)); 

동일하다.

당신은 그것을 테스트하고 첫번째 방법은 단 하나의 액션의 인스턴스를 볼 수 있습니다
dotnetfiddle
그것은 매우 놀라운 일이 될 수 때로는 뒤에서 무슨 일이 일어나고 있는지 발견 할 수 있습니다.

+0

두 번째 방법은 느려 집니까? –

+0

또한 tryroslyn 링크가 작동하지 않습니다 –

+1

@ CodeJoy 이렇게 표시됩니다. 나도 이걸했는지 몰랐어. 나는 두 방법 모두 본질적으로 같을 것이라고 기대했다. (tryroslyn 링크를 복사 할 때 문제가 발생했습니다. 모든 브라우저에서 작동하지 않습니다. –

관련 문제