2016-09-15 2 views
1

C#에서 메서드가 여러 호출간에 변수를 유지하도록 할 방법이 있습니까? 예를 들어 :메서드 호출간에 로컬 변수 유지

private int j = 0; 
private void foo() 
{ 
    int i = calculateSomeValue() + j; 
    j = i; 
} 

내가 변수 j 다른 모든에 액세스 할 수있는 방법을 좋아하지 않는다 : 나는 이런 짓을 했을까

private void foo() 
{ 
    int j; //declare this so as it isn't destroyed with the stack frame. 
    int i = calculateSomeValue() + j; 
    j = i; 
} 

일반적인 방법은 다음과 같이 멤버 변수로 될 것 클래스의 메소드. 게다가 지저분 해 보인다. 메서드가 마지막으로 호출되었을 때 i 값을 추적하는 데 한 메서드에서만 사용될 때 멤버 변수를 정의한다.

멋진/깨끗한 방법으로 가능합니까? 아니면 멤버 변수 방식을 사용하고 잊어 버려야합니까?

+2

클래스 필드 (또는 속성)로 정의하지 않고 j 클래스 범위를 지정하는 방법은 없다고 생각합니다. 다른 사람이 누구인지 알고 싶습니다. –

+5

다른 방법들 중 관심이없는 상태가 있다면, 그 자체로 별도의 유형으로 분류 할 가치가 있는지 고려해보십시오. 그러나 일반적으로, 아니요, 당신은 절대적으로 인스턴스 변수를 가져야합니다. 그것은 대상의 상태의 일부입니다. –

+2

나올 때 미니 클래스처럼 들립니다. –

답변

2

당신은이 라인을 따라,이를 캡슐화하는 작은 작은 중첩 클래스를 사용할 수 있습니다 외부 클래스

public class Test 
{ 
    private int foo() 
    { 
     return nested.foo(); 
    } 

    private int calculateSomeValue() 
    { 
     return 42; 
    } 

    readonly Nested nested = new Nested(); 

    private class Nested 
    { 
     private int j; 

     public int foo() 
     { 
      int i = calculateSomeValue() + j; 
      j = i; 
     } 
    } 
} 

방법은 Nested의 공용 멤버에 액세스 할 수 있습니다, 그래서 그들은 단지에 액세스 할 수 있습니다 이 예에서 foo() - j에 액세스 할 수 없습니다. 그러나 Nested의 메서드는 외부 클래스의 모든 private 멤버에 액세스 할 수 있습니다.

+0

간단한 인스턴스 변수를 사용하는 것보다 나은 이유는 무엇입니까? 필드에 어떤 가치를 유지하고 싶을 때마다 새로운 수업을 시작해야합니까? – Fabjan

+0

@Fabjan OP는 변수가 다른 클래스의 메서드에 액세스 할 수 없도록하는 것이 중요하다고 말했습니다. – Servy

+0

@Fabjan 보통 이런 간단한 코드는 신경 쓸 필요가 없지만 일부 동작을 캡슐화하려는 약간 더 복잡한 코드로 확장됩니다.하지만 너무 복잡하지 않아 완전히 새로운 중첩되지 않은 클래스를 도입해야합니다. 그러나 실제 수업은 일반적으로 이런 종류의 것이 결코 매력적이지 않을 정도로 충분히 작아야합니다. –

1

당신이 물어 보는 범위를 제공하는 다른 방법이 없다고 생각합니다. 이 경우 다른 메소드가 j에 액세스 할 수 있다는 사실은 홀더 객체 내부의 멤버를 캡슐화하는 OOP 개념의 직접적인 결과입니다.

그래서 멤버 변수를 계속 사용하고 다른 방법으로 액세스 할 수 있는지 걱정하지 마십시오. 어떤 이유로 변수에 액세스하는 다른 메소드를 사용하지 않아야하는 경우, 주어진 예제가 정당화되지는 않았지만 자체 유형으로 리팩터링을 고려해야합니다.

희망이 도움이됩니다.

0

는 C 이것은 정적 로컬 변수 기능이 의도적으로 포함되지 않은 C에서

void foo() 
{ 
    static int j; 
    int i = calculateSomeValue() + j; 
    j = i; 
} 

가능하다.

j의 유효 기간에 따라 몇 가지 옵션이 있습니다. 그냥 루프를 사용하지 않으려는 연속 통화 및 몇 가지 이유로 그것을 필요로하는 경우 더 많은 제어 또는 긴 수명의 반대 방향 방법 것을 원한다면, 당신은 재귀 접근

private void foo() 
{ 
    foo(0); 
} 

private void foo(int j) 
{ 
    int i = calculateSomeValue() + j; 
    foo(j); 
} 

갈 수 이 기능을 일반 클래스 나 개인 클래스로 기존 클래스에 중첩시킬 수있는 클래스에 푸시해야합니다.

public class ParentClass() 
{ 
    FooClass bar = new FooClass(); 

    private class FooClass() 
    { 
     private int j = 0; 
     public void foo() 
     { 
      int i = calculateSomeValue() + j; 
      j = i; 
     } 

     private int calculateSomeValue() 
     { 
      // 
     } 
    } 

    private void DoStuff() 
    { 
     bar.foo(); 
    } 
} 

또한 처음에 변수를 보호 할만한 가치가 있다면 다시 무게를 재는 것이 좋습니다.

+0

동일하지는 않습니다. C의 정적 로컬은 해당 클래스의 모든 인스턴스와 공유됩니다. C#의 필드는 각 인스턴스에 대해 별도입니다. –

+0

C에는 클래스가 없습니다 (정적이지만 범위는 기본적으로 전역입니다). 아마도 C++을 사용하면 더 조심해야하지만 경험이 없습니다. 모든 게시 된 C# 메서드에 관계없이 클래스의 범위 내에 포함될 것입니다. – plast1k

0

클로저를 사용하여 불쾌한 방법이 있습니다. 그러나 그것은 당신이 익명의 함수로 당신의 메소드를 정의하고 정의 된 전역 메소드로 싸여 야 함을 의미합니다. 이것에 대한 학문적 인 운동과 분명히 생산 솔루션이 아니라고 생각하십시오. 실생활의 해결책을 얻으려면 분명히 별도의 수업을 고려하십시오.

static void Main(string[] args) 
{ 
    var j = 0; 

    Func<int> calculateSomeValue =() => 
    { 
     return 41; 
    }; 

    Action myFoo =() => 
    { 
     int i = calculateSomeValue() + j; 
     j = i; 
    }; 
} 
관련 문제